2016-11-10 1 views
5

Ich bin relativ neu in AWS und ich versuche, meine E-Mail über Lambda-Funktionen zu verarbeiten. Ich habe diese in node.js gebaut:SES: Zugriff auf E-Mail-Körper in Lambda-Funktion

'use strict'; 

exports.handler = (event, context, callback) => { 

    var http = require('http'); 
    var data = JSON.stringify(event); 

    var options = { 
     host: 'my.host', 
     port: '80', 
     path: '/my/path', 
     method: 'POST', 
     headers: { 
      'Content-Type': 'application/json; charset=utf-8', 
      'Content-Length': data.length 
     } 
    }; 

    var req = http.request(options, function(res) { 
     var msg = ''; 

     res.setEncoding('utf8'); 
     res.on('data', function(chunk) { 
      msg += chunk; 
     }); 
     res.on('end', function() { 
      console.log(JSON.parse(msg)); 
     }); 
    }); 

    req.write(data); 
    req.end(); 
}; 

ich mit dem Endpunkt getestet habe und es funktioniert perfekt, das Problem ist, dass ich nur realisiert nun, dass der Körper der Nachricht nie gesendet wird. Wie kann ich auf den Nachrichtentext zugreifen, um ihn zu senden und von meiner API verarbeitet zu werden?

Wenn Sie eine Probe von whats gesendet haben, lassen Sie mich wissen.

Antwort

4

Also was ich tat, war das Speichern der E-Mail in einem S3-Bucket empfangen, als die Benachrichtigung meiner API, dass eine neue E-Mail angekommen ist (Senden des Dateinamens). Endlich gelesen von S3, geparst, gespeichert und gelöscht von S3, in meiner API.

SES Regeln: SES rules

Lambda anmelde Funktion:

Beachten Sie, dass der Name der von der ersten Regel erstellt S3-Datei die gleiche wie die Nachrichten-ID, daher 'fileName': event.Records[0].ses.mail.messageId .

'use strict'; 

exports.handler = (event, context, callback) => { 

    var http = require('http'); 
    var data = JSON.stringify({ 
     'fileName': event.Records[0].ses.mail.messageId, 
    }); 

    var options = { 
     host: 'my.host', 
     port: '80', 
     path: '/my/path', 
     method: 'POST', 
     headers: { 
      'Content-Type': 'application/json; charset=utf-8', 
      'Content-Length': data.length 
     } 
    }; 

    var req = http.request(options, function(res) { 
     var msg = ''; 

     res.setEncoding('utf8'); 
     res.on('data', function(chunk) { 
      msg += chunk; 
     }); 
     res.on('end', function() { 
      console.log(JSON.parse(msg)); 
      context.succeed(); 
     }); 
    }); 

    req.write(data); 
    req.end(); 
}; 

Api-Funktion (PHP - Laravel):

Beachten Sie, dass ich eine E-Mail-Parser bin mit, die auf Plancake Email Parser (Link here) mit einigen Änderungen meiner eigenen basiert und wenn nötig, werde ich bearbeiten, um die Quelle anzuzeigen.

public function process_incoming_email(Request $request) 
{ 
    $current_time = Carbon::now()->setTimezone('Brazil/East'); // ALL TIMEZONES: http://us.php.net/manual/en/timezones.others.php 

    try 
    { 
     if ($request->has('fileName') 
     { 
      $file_name = $request->input('fileName'); 

      // GET CREDENTIALS AND AUTHENTICATE 
      $credentials = CredentialProvider::env(); 
      $s3 = new S3Client([ 
       'version' => 'latest', 
       'region' => 'my-region', 
       'credentials' => $credentials 
      ]); 

      // FECTH S3 OBJECT 
      $object = $s3->GetObject(['Bucket' => 'my-bucket', 'Key' => $file_name]); 
      $body = $object['Body']->getContents(); 

      // PARSE S3 OBJECT 
      $parser = new EmailParser($body); 
      $receivers = ['to' => $parser->getTo(), 'cc' => $parser->getCc()]; 
      $from = $parser->getFrom(); 
      $body_plain = $parser->getPlainBody(); 
      $body_html = $parser->getHTMLBody(); 
      $subject = $parser->getSubject(); 

      $error_message; 

      // PROCESS EACH RECEIVER 
      foreach ($receivers as $type => $type_receivers) 
      { 
       foreach ($type_receivers as $receiver) 
       { 
        // PROCESS DOMAIN-MATCHING RECEIVERS 
        if(preg_match("/@(.*)/", $receiver['email'], $matches) && $matches[1] == self::HOST) 
        { 
         // INSERT NEW EMAIL 
         $inserted = DB::table('my-emails')->insert([ 
          // ... 
         ]); 
        } 
       } 
      } 

      // ADD ERROR LOG IF PARSER COULD NOT FIND EMAILS 
      if($email_count == 0) 
      { 
       DB::table('my-logs')->insert(
        ['sender' => $request->ip(), 'type' => 'error', 'content' => ($error_message = 'Could not parse received email or find a suitable user receiving email.') . ' File: ' . $file_name] 
       ); 
      } 
      // DELETE OBJECT FROM S3 IF INSERTED 
      else if(count($emails) == $email_count) 
      { 
       $s3->deleteObject(['Bucket' => 'my-bucket', 'Key' => $file_name]); 

       // RETURN SUCCESSFUL JSON RESPONSE 
       return Response::json(['success' => true, 'receivedAt' => $current_time, 'message' => 'Email successfully received and processed.']); 
      } 
      // ADD ERROR LOG IF NOT INSERTED 
      else 
      { 
       DB::table('my-logs')->insert(
        ['sender' => $request->ip(), 'type' => 'error', 'content' => ($error_message = 'Inserted ' . count($emails) . ' out of ' . $email_count . ' parsed records.') . ' File: ' . $file_name] 
       ); 
      } 
     } 
     else 
     { 
      // ERROR: NO fileName FIELD IN RESPONSE 
      DB::table('my-logs')->insert(
       ['sender' => $request->ip(), 'type' => 'error', 'content' => ($error_message = 'Incorrect request input format.') . ' Input: ' . json_encode($request->all())] 
      ); 
     } 
    } 
    // ERROR TREATMENT 
    catch(Exception $ex) 
    { 
     DB::table('my-logs')->insert(
      ['sender' => $request->ip(), 'type' => 'error', 'content' => ($error_message = 'An exception occurred while processing an incoming email.') . ' Details: ' . $ex->getMessage()] 
     ); 
    } 

    // RETURN FAILURE JSON RESPONSE 
    return Response::json(['success' => false, 'receivedAt' => $current_time, 'message' => $error_message]); 
} 
+1

Danke für das Nachschlagen. Ran in das gleiche Problem. Scheint etwas albern (um nicht zu sagen ineffizient), dass wir durch so viele Schleifen springen müssen, um an den Nachrichtentext zu gelangen. Ist das immer noch dieselbe Lösung, die Sie heute verwenden? – DaveJ

+1

@DaveJ Leider ja:/ –

+1

@MatheusSimon - Ich versuche etwas sehr ähnliches zu bekommen, das mit Laravel 5.4 läuft. Ich benutze SES um alle eingehenden Emails zu akzeptieren und sie werden momentan in S3 gespeichert. Mein ursprünglicher Gedanke war es sie zu parsen mit einer JavaScript-Funktion auf Lambda und dann senden sie an Laravel in DB speichern und in der Anwendung anzeigen, Kann ich Lambda insgesamt mit dem E-Mail-Parser vermeiden, die Sie verwendet haben, indem Sie das S3-Objekt, das SES speichert? Schätze jede Hilfe, Danke. – Birdy

1

Ich habe eine sehr ähnliche Lösung mit dem anderen, aber mit einem weniger Schritt. Es ist möglich, Lambda-Trigger zu setzen. Also habe ich einen Bucket myemailbucket erstellt und die E-Mail von SES an diesen Bucket gesendet. Dann habe ich den Auslöser für meine Lambda-Funktion zu einem beliebigen create-Ereignis in s3 im Bucket myemailbucket geändert.