用jinja做了个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小项目的更多相关文章
- 最近做的一个Spring Boot小项目,欢迎大家访问 http://39.97.115.152/
最近做的一个Spring Boot小项目,欢迎大家访问 http://39.97.115.152/,帮忙找找bug,网站里有源码地址 网站说明 甲壳虫社区(Beetle Community) 一个开源 ...
- 小项目特供 贪吃蛇游戏(基于C语言)
C语言写贪吃蛇本来是打算去年暑假写的,结果因为ACM集训给耽搁了,因此借寒假的两天功夫写了这个贪吃蛇小项目,顺带把C语言重温了一次. 是发表博客的前一天开始写的,一共写了三个版本,第一天写了第一版,第 ...
- Vue小项目二手书商城:(一)准备工作、组件和路由
本项目基于vue2.5.2,与低版本部分不同之处会在(五)参考资料中提出 完整程序:https://github.com/M-M-Monica/bukesi 实现内容: 资源准备(mock数据) 组件 ...
- 用struts2标签如何从数据库获取数据并在查询页面显示。最近做一个小项目,需要用到struts2标签从数据库查询数据,并且用迭代器iterator标签在查询页面显示,可是一开始,怎么也获取不到数据,想了许久,最后发现,是自己少定义了一个变量,也就是var变量。
最近做一个小项目,需要用到struts2标签从数据库查询数据,并且用迭代器iterator标签在查询页面显示,可是一开始,怎么也获取不到数据,想了许久,最后发现,是自己少定义了一个变量,也就是var变 ...
- 用原生javascript做的一个打地鼠的小游戏
学习javascript也有一段时间了,一直以来分享的都是一些概念型的知识,今天有空做了一个打地鼠的小游戏,来跟大家分享一下,大家也可以下载来增加一些生活的乐趣,下面P出代码:首先是HTML部分代码: ...
- delphi 利用HTTP的POST方法做个在线翻译的小工具 good
最近做了一个英汉小翻译的东东,用的是VC,ADO + Access访问数据库,单词数据库是从金山打字通2002弄来的.后来想了想,想再加个在线翻译的功能,记得经常使用GOOGLE翻译网站的在线翻译,也 ...
- 又见angular----步一步做一个angular4小项目
这两天看了看angular4的文档,发现他和angular1.X的差别真的是太大了,官方给出的那个管理英雄的Demo是一个非常好的入门项目,这里给出一个管理个人计划的小项目,从头至尾一步一步讲解如何去 ...
- 在做关于NIO TCP编程小案例时遇到无法监听write的问题,没想到只是我的if语句的位置放错了位置,哎,看了半天没看出来
在做关于NIO TCP编程小案例时遇到无法监听write的问题,没想到只是我的if语句的位置放错了位置,哎,看了半天没看出来 贴下课堂笔记: 在Java中使用NIO进行网络TCP套接字编程主要以下几个 ...
- 17、 利用扇贝网:https://www.shanbay.com/, 做个测单词的小工具。
先说下,我可以说完全没有看题目要求,我只看了下扇贝网的单词测试工具就开始编码了,写出来的代码尽可能的模仿了网站上的效果. 因为把问题搞复杂了,在这个练习上耽误了很长时间,最后都不想写了,所以代码有些混 ...
- 毕业设计代做,各种系统微服务项目ssm项目,员工管理系统,微信小程序,购物商城,二手商城系统,销售系统,等等
毕业设计代做,各种系统,微服务项目,ssm项目 小程序,商城等,期末作业等都可以,价格好说,长期接单, 有项目说明书,软件介绍相关文档,答辩的时候包过,知识点对接好,给你讲解等, 毕业设计代做,各种系 ...
随机推荐
- UVa 11384 Help is needed for Dexter
分析题目以后得出,对于一个连续等差递增的序列,例如1,2,3,4,5,6,每次选择其中后一半,减去能减的最大数,则是最优操作. 上述序列经过一次操作后变为1,2,3,0,1,2,此时可抛弃后一半(已经 ...
- POJ3468 A Simple Problem with Integers
Description 给出了一个序列,你需要处理如下两种询问. "C abc"表示给[a, b]区间中的值全部增加c (-10000 ≤ c ≤ 10000). "Q ...
- Windows网络驱动、NDIS驱动(微端口驱动、中间层驱动、协议驱动)、TDI驱动(网络传输层过滤)、WFP(Windows Filtering Platform)
catalog . 引言 . Windows 2000网络结构和OSI模型 . NDIS驱动 . NDIS微端口驱动编程实例 . NDIS中间层驱动编程实例 . NDIS协议层驱动编程实例 . TDI ...
- C#产生随机颜色
在.net Framework中提供了一个专门用来产生随机数的类System.Random.C#可以用Random产生随机的R.G.B值,从而生成随机的颜色. 对于随机数,计算机不可能产生完全随机的数 ...
- iOS 自定义对象转NSDictionary
我们在向后台Post数据的时候,常常需要把某个对象作为参数,比如在AF的框架中,我们进行Post时,其中的para参数就是需要NSdictionary的 Alamofire.request(.POST ...
- A.Kaw矩阵代数初步学习笔记 10. Eigenvalues and Eigenvectors
“矩阵代数初步”(Introduction to MATRIX ALGEBRA)课程由Prof. A.K.Kaw(University of South Florida)设计并讲授. PDF格式学习笔 ...
- 使用IntelliJ IDEA和Maven构建Java web项目并打包部署
爱编程爱分享,原创文章,转载请注明出处,谢谢! http://www.cnblogs.com/fozero/p/6120375.html 一.背景 现在越来越多的人使用IntelliJ IDEA工具进 ...
- wpf button的mouse(leftbutton)down/up,click事件不响应解决办法
按照WPF的帮助说明,某些控件的路由事件被内部处理了,已经被标记为Handled,自行定义的事件处理代码便不再起作用了,有时候会很郁闷! 不过WPF提供了必要的方法. ...
- python3,交互模式,无法使用ctrl和方向键,需要和ctrl一块用
转自csdn博客 http://blog.csdn.net/pumaadamsjack/article/details/52447989 https://pypi.python.org/pypi/re ...
- oneM2M标准发展神速 实现万物联网的愿景
http://m2m.iot-online.com/news/2013102224849.html oneM2M则将负责解决独立于接取网路中通用的M2M服务层的关键需求:使其可更方便地嵌入于各种软硬体 ...