6

Amazon SES 文档对我来说不是很清楚。因此,如果您可以帮助我发送包含 PDF 附件的原始文本电子邮件的示例,这将对我有很大帮助。我使用 Python 2.5 和 Google App 引擎。我必须使用“原始”,因为如果我包含附件,那是唯一的 SES 选项。

我目前的问题:

  • post请求的内容是什么。
  • 我应该将哪些消息字段放在标题中。
  • 如何处理“returnPath”。
  • 如何处理正文。它应该是: Content-Type: text/plain; 字符集=UTF-8;格式=流动;delsp=是的。内容传输编码:base64
  • 如何为这篇文章构建 HMAC 签名。我知道如何制作签名,但原始字符串如何查找签名函数。
4

3 回答 3

5

此处使用多部分正文(纯/html/附件)发送 SES 原始电子邮件的示例代码:

from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from google.appengine.api import urlfetch
from google.appengine.runtime import DeadlineExceededError
import urllib
import hmac
import base64
import hashlib
from datetime import datetime
import logging


def ses_multi_part(msg_subject, msg_to, msg_body='', msg_cc=None, msg_bcc=None, file_name=None, file_reader=None,
                      msg_type='plain', msg_from='noreply@....', msg_reply_to='contact@....'):
    """ send an html or plain e-mail. Use file_name and file_reader to pass an attachment
        inspiration: https://codeadict.wordpress.com/2010/02/11/send-e-mails-with-attachment-in-python/
    """

    msg = MIMEMultipart()
    msg.set_charset("utf-8")

    msg['Subject'] = msg_subject
    msg['From'] = msg_from
    msg['Reply-to'] = msg_reply_to
    msg['To'] = msg_to
    if msg_cc:
        msg['Cc'] = msg_cc
    if msg_bcc:
        msg['Bcc'] = msg_bcc
    logging.debug(msg)

    msg.preamble = 'Multipart massage.\n'

    part = MIMEText(msg_body, msg_type, "utf-8")
    msg.attach(part)

    if file_name:
        part = MIMEApplication(file_reader.read())
        part.add_header('Content-Disposition', 'attachment', filename=file_name)
        msg.attach(part)

    return msg.as_string()


class SES(object):
    """ SES send RAW e-mail
        inspiration: https://github.com/richieforeman/python-amazon-ses-api/blob/master/amazon_ses.py
    """

    def __init__(self, accessKeyID, secretAccessKey, return_path='contact@....'):

        self._accessKeyID = accessKeyID
        self._secretAccessKey = secretAccessKey
        self.ses_return_path = return_path

    def _getSignature(self, dateValue):

        h = hmac.new(key=self._secretAccessKey, msg=dateValue, digestmod=hashlib.sha256)
        return base64.b64encode(h.digest()).decode()

    def _getHeaders(self):

        headers = {'Content-type': 'application/x-www-form-urlencoded', 'Return-Path': self.ses_return_path}
        d = datetime.utcnow()
        dateValue = d.strftime('%a, %d %b %Y %H:%M:%S GMT')
        headers['Date'] = dateValue
        signature = self._getSignature(dateValue)
        headers['X-Amzn-Authorization'] = 'AWS3-HTTPS AWSAccessKeyId=%s, Algorithm=HMACSHA256, Signature=%s' % (self._accessKeyID, signature)
        return headers

    def _performAction(self, actionName, params=None):

        if not params:
            params = {}
        params['Action'] = actionName

        response = None
        #https://email.us-east-1.amazonaws.com/

        retry = 0  # download error retry
        while retry <= 1:  # dan een eenmalige retry
            try:
                url = 'https://email.us-east-1.amazonaws.com'
                response = urlfetch.fetch(url=url, payload=urllib.urlencode(params), method=urlfetch.POST, headers=self._getHeaders())
                break
            except (urlfetch.DownloadError, DeadlineExceededError), e:
                logging.debug('Amazon SES download or deadline error : %d' % (retry + 1))
                if retry == 0:
                    retry += 1
                    continue  # retry
                else:
                    logging.warning('fetcherror' + str(e))
                    raise  # bij een dubbele fout stoppen

        if response.status_code != 200:
            logging.warning(response.headers)
            logging.warning(response.content)
            raise ValueError('status_code : %s' % (str(response.status_code)))

        logging.debug(response.content)
        return response.content

    def sendRawEmail(self, raw_msg_data):

        return self._performAction("SendRawEmail", params={"RawMessage.Data": base64.b64encode(raw_msg_data)})

示例用法:

ses = SES(settings.AMAZON_ACCESS_KEY_ID, settings.AMAZON_SECRET_ACCESS_KEY, settings.SES_RETURN_PATH[country])
raw_msg_data = ses_multi_part(msg_subject=subject.encode('utf-8'), msg_to=mail_to, msg_body=body_text.encode('utf-8'),
                                 msg_bcc=settings.MAIL_BCC, msg_reply_to=reply_to, msg_from=sender, msg_type=msg_type)
ses.sendRawEmail(raw_msg_data)
于 2015-07-09T00:00:13.023 回答
1

本要点概述了我正在使用的程序。它主要来自遵循此处给出的示例。

于 2012-06-06T17:58:54.090 回答
0

当您可以通过他们的标准 SMTP 接口发送附件和所有内容时,为什么要在他们的 API 中使用 raw 呢?此外,我上次检查 raw 不支持 BCC。

SMTP 接口:http ://docs.amazonwebservices.com/ses/latest/DeveloperGuide/SMTP.html

批准的 MIME 类型列表(否则 SES 会生气):http ://docs.amazonwebservices.com/ses/latest/DeveloperGuide/MIMETypes.html

于 2012-08-03T16:01:20.397 回答