2016-11-10 11 views
5

AWSは比較的新しいので、ラムダ機能を使用してメールを処理しようとしています。私はNode.jsの中で、このいずれかを構築しました:SES:ラムダファンクション内のメール本文へのアクセス

'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(); 
}; 

私はエンドポイントでテストしてみたし、それが完璧に動作しますが、問題は、私はちょうど今、メッセージの本文が送信されることはありませんことに気づいていることです。メッセージの本文にアクセスして送信し、APIで処理するにはどうすればよいですか?

送信されたwhatsのサンプルを見る必要がある場合はお知らせください。

答えて

4

私はS3バケツに受け取ったメールを、新しいメールが到着した(ファイル名を送信した)ことをAPIに通知するよりも保存していました。 S3から読み込まれ、解析され、S3に格納され、S3から削除されます。

SESルール: SES rules

ラムダ通知機能:最初の規則によって作成されたS3ファイルの名前は'fileName': event.Records[0].ses.mail.messageIdしたがって、メッセージIDと同じであることを

注。

'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関数(PHP - Laravel):私は私自身のいくつかの変更をPlancakeメールパーサ(リンクhere)に基づいている電子メールのパーサを使用してい

注意必要に応じて編集してソースを表示します。

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

フォローアップしていただきありがとうございます。同じ問題に遭遇する。私たちがメッセージ本文に到達するためには非常に多くのループを飛び越えなければならないということはちょっとばかげています(非効率的ではありません)。これはあなたが今日使っているのと同じ解決策ですか? – DaveJ

+1

@DaveJ残念ながらyes:/ –

+1

@MatheusSimon - 私は自分自身とlaravel 5.4で動作しているのと非常によく似たものを得ようとしています。私はSESを使ってすべての着信電子メールを受け取り、現在S3に保存されています。 Lambdaのjavascript関数を使用してlaravelに送信してDBに格納し、アプリケーションに表示します。SESストアのS3オブジェクトをフェッチして使用した電子メールパーサーでlambdaを完全に回避できますか?何か助けをありがとう、ありがとう。 – Birdy

1

私は他のものと非常に類似した解決策を持っていますが、1つの少ないステップで。ラムダトリガを設定することは可能です。そこで、バケットmyemailbucketを作成し、そのバケットにSESからメールを送りました。次に、私のラムダ関数のトリガをバケットのs3のイベントを作成するものに変更しましたmyemailbucket

関連する問題