寻找发送原始邮件(包括附件)的Amazon SES示例

vos*_*usa 6 python email google-app-engine amazon-web-services amazon-ses

亚马逊SES文档对我来说并不清楚.因此,如果您可以通过示例发送原始文本电子邮件(包括PDF附件)来帮助我,这将对我有所帮助.我使用Python 2.5和Google App引擎.我必须使用"raw",因为如果我包含附件,这是唯一的SES选项.

我现在的问题:

  • 帖子请求的内容是什么.
  • 我应该在标题中添加哪些消息字段.
  • 如何处理"returnPath".
  • 如何处理文本正文.它应该是:Content-Type:text/plain; 字符集= UTF-8; 格式=流动; delsp = YES.内容传输编码:base64
  • 如何为此帖子构建HMAC签名.我知道如何签名,但原始字符串如何查找签名函数.

vos*_*usa 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)})
Run Code Online (Sandbox Code Playgroud)

用法示例:

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)
Run Code Online (Sandbox Code Playgroud)