如何:电子邮件服务器亚马逊?

HOWTO: Email Server Amazon?

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

虽然它有效,但我对这个解决方案并不完全满意,有谁知道任何 other/better 方法来解决这个接收-存储-访问问题?

提前致谢。

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

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

但我还是会在这里重新发布:

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

SES 规则:

Lambda 通知函数:

Note that the name of the S3 file created by the first rule is the same as the messages id, hence '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):

Note that I'm using an email parser that's based on Plancake Email Parser (link here) with some changes of my own and if needed I'll edit to show the source.

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]);
}