寻找发送包含附件的原始邮件的Amazon SES示例
我对亚马逊SES的文档不是很明白。所以如果你能给我一个例子,教我怎么发送包含PDF附件的纯文本邮件,那对我帮助很大。我使用的是Python 2.5和Google App Engine。因为我需要包含附件,所以只能使用“raw”这个选项。
我现在遇到的问题有:
- 发请求时,内容应该是什么。
- 邮件头里应该放哪些信息。
- 如何处理“returnPath”。
- 如何处理邮件的文本内容。它应该是:Content-Type: text/plain; charset=UTF-8; format=flowed; delsp=yes。Content-Transfer-Encoding: base64。
- 我该如何构建这个请求的HMAC签名。我知道怎么生成签名,但原始字符串在签名函数中应该是什么样子的。
3 个回答
0
为什么要使用他们的原始接口(raw API),而不是通过他们的标准SMTP接口发送附件和其他内容呢?而且,上次我查看的时候,原始接口似乎不支持BCC(密件抄送)。
SMTP接口:http://docs.amazonwebservices.com/ses/latest/DeveloperGuide/SMTP.html
被批准的MIME类型列表(否则SES会生气):http://docs.amazonwebservices.com/ses/latest/DeveloperGuide/MIMETypes.html
5
这里有一个示例代码,教你如何使用SES发送原始电子邮件,邮件内容可以包含多种格式(纯文本/HTML/附件):
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)