用jinja做了个E-Letter小项目

本文详细记录了一次使用Python通过SMTP协议发送HTML邮件时遇到的Exchange Server邮件石沉大海的问题,并提供了排查过程和最终解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

做了一个html E-Letter项目.
邮件模板采用jinja2, html 邮件内容生成简直太爽了.
整个项目开发只用了2个小时, 调试却花了大半天时间, 生成的邮件总是发不出去.
于是, 打开 smtp 的debuglevel, 发现邮件已经mail queue了, 但就是收不到邮件. mail server是exchange. 之前用java写过类似的程序也没有问题(也是走smtp协议发送html邮件). 为什么这次用python实现却有问题?
怀疑过python smtp模块用法, 怀疑过python smtp的html写法, 怀疑过smtp subject和content不支持unicode. 最终都被排除.
最后终于定位到元凶: 邮件的subject只要包含" Please check."这13个字符, 邮件就会石沉大海. 难道是exchange server设了某种规则?

#------------------
资料:
#------------------
cnblogs 小五义的文章不错,  <<python发送各类邮件的主要方法>>,
 http://www.cnblogs.com/xiaowuyi/archive/2012/03/17/2404015.html

#------------------
代码结构
#------------------
下面简单描述一下项目的结构, 在我的脚手架项目基础上, 做了少量的裁剪, 并增加两个目录, scripts和templates, scripts目录存放E-Letter生成和发送脚本, templates目录存放E-Letter的模板.
并附上 mail_service.py, 修改了网上找的代码, 用来发送 html 邮件.  
py_package
      |--scripts
               |--check1.py
               |--check2.py
      |--templates
               |--check1.html
               |--check2.html
#  -*- coding: utf-8 -*-
# check1.py  '''
Created on 2014-5-23 '''  from  __future__  import absolute_import           import jinja2  from jinja2.loaders  import FileSystemLoader def get_template(file_name): '''
    get template html with jinja2 format in templates folder '''
    template_path=os.path.join(os.path.dirname(os.path.dirname( __file__)), ' templates ')
    template_env = jinja2.Environment(loader=FileSystemLoader(template_path))        return template_env.get_template(file_name) def check():
    template=get_template( ' check1.html ')
    something= ' something here '
    mail_body=template.render(something=something)
    mail_sender=HtmlMailSender() 
    mail_subject= ' Some subject here ' # mail_subject='Please check.'  #cannot send out, why?      mail_to=[ ' a@corp.com ', ' b.corp.com ']
    mail_cc=[] 
    mail_sender.send_html_mail(mail_to,mail_cc,mail_subject,mail_body)    
     #  -*- coding: utf-8 -*-
# conf.py  '''
Created on 2014-6-23 ''' from  __future__  import absolute_import import logging # #logging log_level=logging.INFO  # email setting  smtp_host= " 10.10.10.10 " 
smtp_port=25 
smtp_over_ssl=False
mail_user= " a@corp.com " 
mail_pwd= ""     #  if no auth required, set pwd as empty  
    #  -*- coding: utf-8 -*-
# mail_service.py  '''
Created on 2014-6-23 ''' from  __future__  import absolute_import import logging from .  import conf class HtmlMailSender(object):
    logger=logging.getLogger( __name__) def  __init__(self): # read mail settings from configure file         self.smtp_host=conf.smtp_host
        self.smtp_port=conf.smtp_port
        self.smtp_over_ssl=conf.smtp_over_ssl
        self.mail_user=conf.mail_user
        self.mail_pwd=conf.mail_pwd         def send_html_mail(self, to_list, cc_list, subject, body):
        self.logger.info( ' send_html_mail() called. ') import smtplib from email.mime.text  import MIMEText   from email.mime.multipart  import MIMEMultipart   #  Construct email         msgRoot = MIMEMultipart( ' related ')
        msgRoot[ ' Subject '] = subject    
        msgRoot[ ' From '] = self.mail_user  
        msgRoot[ ' To '] =  " , ".join(to_list)  
        msgRoot[ ' CC '] = " , ".join(cc_list)    # msgRoot['BCC'] =",".join(cc_list)         msgRoot.preamble =  ' This is a multi-part message in MIME format. ' #  Encapsulate the plain and HTML versions of the message body in an          #  'alternative' part, so message agents can decide which they want to display.         msgAlternative = MIMEMultipart( ' alternative ')
        msgRoot.attach(msgAlternative) # Add plain content         msgText = MIMEText( ' This is HTML mail. If you see this message, which means you will not see the real mail content. ', ' plain ')
        msgAlternative.attach(msgText) # add html content         msgText = MIMEText(body,  ' html ')
        msgAlternative.attach(msgText) try: if  not self.smtp_over_ssl: if self.smtp_port== '':
                    s = smtplib.SMTP(self.smtp_host) else:
                    s = smtplib.SMTP(self.smtp_host, self.smtp_port) else: if self.smtp_port== '':
                    s = smtplib.SMTP_SSL(self.smtp_host) else:
                    s = smtplib.SMTP_SSL(self.smtp_host, self.smtp_port)
            s.set_debuglevel(True)   #  print stmp actions to stdout              if self.mail_pwd :
                s.login(self.mail_user,self.mail_pwd)  
            to_addrs=to_list+cc_list
            s.sendmail(self.mail_user ,to_addrs, msgRoot.as_string())   # s.sendmail(from_addr ,to_addrs, 'test message')             s.quit()    
            self.logger.info( """ Mail sent. Find details below, 
            to_list: %s 
            cc_list: %s 
            subject: %s 
            body: %s """%(to_list, cc_list, subject, body))                      return True   except Exception, ex:  
            self.logger.exception(ex)   return False      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值