做了一个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      

用jinja做了个E-Letter小项目的更多相关文章

  1. 最近做的一个Spring Boot小项目,欢迎大家访问 http://39.97.115.152/

    最近做的一个Spring Boot小项目,欢迎大家访问 http://39.97.115.152/,帮忙找找bug,网站里有源码地址 网站说明 甲壳虫社区(Beetle Community) 一个开源 ...

  2. 小项目特供 贪吃蛇游戏(基于C语言)

    C语言写贪吃蛇本来是打算去年暑假写的,结果因为ACM集训给耽搁了,因此借寒假的两天功夫写了这个贪吃蛇小项目,顺带把C语言重温了一次. 是发表博客的前一天开始写的,一共写了三个版本,第一天写了第一版,第 ...

  3. Vue小项目二手书商城:(一)准备工作、组件和路由

    本项目基于vue2.5.2,与低版本部分不同之处会在(五)参考资料中提出 完整程序:https://github.com/M-M-Monica/bukesi 实现内容: 资源准备(mock数据) 组件 ...

  4. 用struts2标签如何从数据库获取数据并在查询页面显示。最近做一个小项目,需要用到struts2标签从数据库查询数据,并且用迭代器iterator标签在查询页面显示,可是一开始,怎么也获取不到数据,想了许久,最后发现,是自己少定义了一个变量,也就是var变量。

    最近做一个小项目,需要用到struts2标签从数据库查询数据,并且用迭代器iterator标签在查询页面显示,可是一开始,怎么也获取不到数据,想了许久,最后发现,是自己少定义了一个变量,也就是var变 ...

  5. 用原生javascript做的一个打地鼠的小游戏

    学习javascript也有一段时间了,一直以来分享的都是一些概念型的知识,今天有空做了一个打地鼠的小游戏,来跟大家分享一下,大家也可以下载来增加一些生活的乐趣,下面P出代码:首先是HTML部分代码: ...

  6. delphi 利用HTTP的POST方法做个在线翻译的小工具 good

    最近做了一个英汉小翻译的东东,用的是VC,ADO + Access访问数据库,单词数据库是从金山打字通2002弄来的.后来想了想,想再加个在线翻译的功能,记得经常使用GOOGLE翻译网站的在线翻译,也 ...

  7. 又见angular----步一步做一个angular4小项目

    这两天看了看angular4的文档,发现他和angular1.X的差别真的是太大了,官方给出的那个管理英雄的Demo是一个非常好的入门项目,这里给出一个管理个人计划的小项目,从头至尾一步一步讲解如何去 ...

  8. 在做关于NIO TCP编程小案例时遇到无法监听write的问题,没想到只是我的if语句的位置放错了位置,哎,看了半天没看出来

    在做关于NIO TCP编程小案例时遇到无法监听write的问题,没想到只是我的if语句的位置放错了位置,哎,看了半天没看出来 贴下课堂笔记: 在Java中使用NIO进行网络TCP套接字编程主要以下几个 ...

  9. 17、 利用扇贝网:https://www.shanbay.com/, 做个测单词的小工具。

    先说下,我可以说完全没有看题目要求,我只看了下扇贝网的单词测试工具就开始编码了,写出来的代码尽可能的模仿了网站上的效果. 因为把问题搞复杂了,在这个练习上耽误了很长时间,最后都不想写了,所以代码有些混 ...

  10. 毕业设计代做,各种系统微服务项目ssm项目,员工管理系统,微信小程序,购物商城,二手商城系统,销售系统,等等

    毕业设计代做,各种系统,微服务项目,ssm项目 小程序,商城等,期末作业等都可以,价格好说,长期接单, 有项目说明书,软件介绍相关文档,答辩的时候包过,知识点对接好,给你讲解等, 毕业设计代做,各种系 ...

随机推荐

  1. 关于《加密与解密》的读后感----对dump脱壳的一点思考

    偶然翻了一下手机日历,原来今天是夏至啊,时间过的真快.ISCC的比赛已经持续了2个多月了,我也跟着比赛的那些题目学了2个月.......虽然过程很辛苦,但感觉还是很幸运的,能在大三的时候遇到ISCC, ...

  2. List<List<String>>

    package list; import java.util.ArrayList; import java.util.List; public class MyList { public static ...

  3. 分布式存储数据库的Key的随机分布(RP)和顺序分布(OPP)

    在分布式存储数据库的世界中,无论是基于Key/Value的数据库还是Column Base(比如HBase)的数据库,都有一个重要的因子------Key,或者叫RowKey.我们总是根据Key来快速 ...

  4. 屠蛟之路_乘风破浪_FifthDay

    乘风破浪 一艘大船 (我们写的几千行代码) 一片汪洋 (软工耗费的时间) 一群骚年 (一不小心就火了) 为救一位公主 (吃自助餐) 选择去跋山涉水,乘风破浪(解决bug,解决冲突) 毫不畏惧 (韧性) ...

  5. POJ 2892 Tunnel Warfare

    传送门 很神奇的一道题,可以用线段树搞,为了练习treap所以拿treap写了. 其实根据询问,删除那个标号就加入平衡树,然后找到最大的和最小的就好了. 一些很烦人的小细节. //POJ 2892 / ...

  6. elk系列2之multiline模块的使用

    preface 上回说道了elk的安装以及kibana的简单搜索语法,还有logstash的input,output的语法,但是我们在使用中发现了一个问题,我们知道,elk是每一行为一个事件,像Jav ...

  7. 如何让vim编辑器永久显示行号

    在Linux环境下的编辑器有vi.vim.gedit等等.进入这些编辑器之后,为了方便我们需要编辑器显示出当前的行号,可偏偏编辑器默认是不会显示行号的.我们有二种办法可以解决: 第一种是,手动显示:在 ...

  8. Oracle开发常用函数

    max 最大数 自动加 1 create or replace function fun_getmaxlot( vend in varchar2 , domain IN VARCHAR2, tag i ...

  9. $(document).ready、body.Onload()和 $(window).load的区别

    window.load(function(){...})和body.onload()都存在同样一个问题,那都是在页面所有元素(包括html标签以及引用到得所有图片,Flash等媒体)加载完毕后执行的, ...

  10. 《零成本实现Web性能测试:基于Apache JMeter》读书笔记

    1.性能测试概念 性能测试目的: 评估系统能力,验证系统是否符合预期性能指标 识别系统中的弱点 系统调优,改进系统性能 检测长时间运行可能发生的问题,揭示隐含问题 验证稳定性.可靠性 常见性能指标 B ...