【问题标题】:HOWTO: Email Server Amazon?如何:电子邮件服务器亚马逊?
【发布时间】:2017-03-13 01:16:43
【问题描述】:

我正在尝试为我的域构建电子邮件服务器...我现在正在做的是通过 SES 接收电子邮件并将它们存储在 S3 存储桶中,然后当用户访问收件箱时,它会获取新电子邮件并存储它们在我的 EC2 实例数据库中。

虽然它有效,但我对这个解决方案并不完全满意,有没有人知道解决这个接收-存储-访问问题的任何其他/更好的方法?

提前致谢。

【问题讨论】:

  • 某种带有 ses 的“网络邮件”?
  • @nogad 我一直在阅读有关工作邮件的信息(我认为您的意思是),但它似乎无法通过编程方式访问
  • 用户是通过 Web 界面而不是邮件应用程序访问电子邮件?
  • @alexandresaiz 那只是用于邮件营销,我正在努力工作接收端
  • lambda 函数是否可以直接添加到数据库?

标签: php email amazon-web-services amazon-ec2 amazon-ses


【解决方案1】:

我已经解决了这个问题,并在我提出的另一个问题上发布了答案here

但无论如何我都会在这里转发:

所以我所做的是将收到的电子邮件存储在 S3 存储桶中,而不是通知我的 api 新电子邮件已到达(发送文件名)。最后在我的 api 中从 S3 读取、解析、存储和删除。

SES 规则:

Lambda 通知功能:

请注意,第一条规则创建的 S3 文件的名称与消息 ID 相同,因此为 '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 函数(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]);
}

【讨论】:

    【解决方案2】:

    您可以尝试在您的 EC2 实例上安装 postfix (http://www.postfix.org/) 和 dovecot (http://www.dovecot.org/)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-25
      • 1970-01-01
      • 1970-01-01
      • 2015-06-15
      • 1970-01-01
      • 2016-01-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多