Maison  >  Article  >  développement back-end  >  Apprenez-vous un exemple de code Python pour créer un script de courrier électronique automatique

Apprenez-vous un exemple de code Python pour créer un script de courrier électronique automatique

Y2J
Y2Joriginal
2017-04-27 11:58:462813parcourir

Cet article présente principalement les connaissances pertinentes du script de messagerie automatique Python. Il a une très bonne valeur de référence, jetons un oeil avec l'éditeur ci-dessous

Origine

Pendant cette période, j'ai réalisé un script d'envoi d'emails de groupe à amis, afin d'éviter que j'ai fait beaucoup de travail pour entrer dans le spam, je viens de le terminer et le taux d'entrée du spam est de 50%, ce qui, à mon avis, n'est pas mauvais. Je devrai probablement dépenser de l'argent pour acheter un hôte, réfléchissez-y, lancez-le d'abord pendant un mois, voyez l'effet, puis développez-le.

Le script est principalement écrit en Python et ajusté par la bibliothèque smtplib. Ce sont les bases Vous pouvez beaucoup rechercher sur Internet. Aujourd'hui, je vais principalement vous expliquer comment éviter d'entrer dans le système anti-spam et comment. pour construire l'ensemble du système quelques réflexions. Peut-être que je viens de démarrer Python, et il existe de nombreuses mauvaises façons d'écrire. J'espère que vous pourrez le signaler ~

Configuration

Système CentOS7.0

Python 3.4

La version par défaut sous CentOS7.0 est Python 2.7.5. Mettons d'abord à niveau la version Python

#wget https://www.python.org/ftp/python/3.4.3/Python-3.4.3.tgz

Téléchargez Python 3.4. version

#tar -xf Python-3.4.3.tgz
#cd Python-3.4.3/
#./configure
Lors de la configuration ici, vous constaterez peut-être que votre environnement n'a pas l'environnement de compilation gcc installé. Exécutez l'instruction suivante, puis configurez

#yum -y install gcc
#yum -y install gdb
#yum -y install gcc-c++
Compilez et installez

Parce que yum risque de ne pas fonctionner correctement après le remplacement de la version de python, deux fichiers doivent être modifiés
#make
#make install

Changez le #!/usr/bin/python dans l'en-tête de ces deux fichiers dans #!/usr /bin/python2.7, enregistrez et quittez, miam sera ressuscité une fois plein
#vim /usr/bin/yum
#vim /usr/libexec/urlgrabber-ext-down

Après la compilation, définissez python3.4 comme analyse python par défaut.

#ln -s /usr/local/bin/python3.4 /usr/bin/pythonVérifiez la version de Python une fois le lien terminé

#python -VLorsque Python3.4 apparaît, cela indique que la version le changement est terminé

Architecture du système

Apprenez-vous un exemple de code Python pour créer un script de courrier électronique automatiqueCompte : le répertoire utilisé pour stocker le compte de messagerie de l'expéditeur, mon e-mail 163, sina email , sohu email et tom email sont tout ce que j'ai acheté sur Taobao qui peut envoyer des services SMTP. Vous pouvez les obtenir pour moins que le prix d'un repas. Le mot de passe du compte est séparé par [:] et chaque compte est séparé par [. ,].

Common : dossier de classe de référence, qui contient le fichier de configuration du système Rinzhi et le code source du système de journalisation

Conf : fichier de configuration global, actuellement inutile

Image : ressources d'images qui doivent être utilisés dans le processus d'envoi d'e-mails

Journal : fichiers journaux, distingués par date

Logbackups : fichiers de sauvegarde des journaux, utilisés pour sauvegarder les journaux expirés

Envoyer un courrier électronique : use Pour stocker les informations de messagerie du destinataire, utilisez [,] pour séparer les comptes

mail_html.py : Script d'exécution principal

README.md : Instructions utilisateur pour le contrôle de version git, j'utilise le code Le le cloud gère mon code

Système de journalisation

En ce qui concerne les systèmes de script, les journaux jouent un rôle très critique, surtout lorsque votre script tourne mal et que vous devez vérifier quand c'est faux, c'est très important. J'ai également obtenu un morceau de code pour le système de journalisation des journaux sur Internet, je pense que c'est très utile et pour référence de tous~

L'idée principale est d'imprimer le journal. au fichier spécifié et imprimez le journal. Quand j'arrive à l'écran, je ne dirai rien d'autre. Commençons par le code. Parce qu'il est en ligne, je le mettrai en ligne ~

. Le fichier de configuration du système de journalisation
# coding: utf-8

#from lxml import etree
import logging.handlers
import logging
import os
import sys
import time
import datetime

try: 
 import xml.etree.cElementTree as ET 
except ImportError: 
 import xml.etree.ElementTree as ET 

# 提供日志功能
class logger:
 # 先读取XML文件中的配置数据
 # 由于config.xml放置在与当前文件相同的目录下,因此通过 __file__ 来获取XML文件的目录,然后再拼接成绝对路径
 # 这里利用了lxml库来解析XML
 root = ET.parse(os.path.join(os.path.dirname(__file__), 'config.xml')).getroot()
 # 读取日志文件保存路径
 logpath = root.find('logpath').text
 # 读取日志文件容量,转换为字节
 logsize = 1024*1024*int(root.find('logsize').text)
 # 读取日志文件保存个数
 lognum = int(root.find('lognum').text)

 # 添加分天日志名
 now = datetime.datetime.now()
 now_time = now.strftime('%Y%m%d')
 log_file_name = sys.argv[0].split('/')[-1].split('.')[0] + '_' + now_time
 # 日志文件名:由用例脚本的名称,结合日志保存路径,得到日志文件的绝对路径
 logname = os.path.join(logpath, log_file_name)

 # 初始化logger
 log = logging.getLogger()
 # 日志格式,可以根据需要设置
 fmt = logging.Formatter('[%(asctime)s][%(filename)s][line:%(lineno)d][%(levelname)s] %(message)s', '%Y-%m-%d %H:%M:%S')

 # 日志输出到文件,这里用到了上面获取的日志名称,大小,保存个数
 handle1 = logging.handlers.RotatingFileHandler(logname, maxBytes=logsize, backupCount=lognum)
 handle1.setFormatter(fmt)
 # 同时输出到屏幕,便于实施观察
 handle2 = logging.StreamHandler(stream=sys.stdout)
 handle2.setFormatter(fmt)
 log.addHandler(handle1)
 log.addHandler(handle2)

 # 设置日志基本,这里设置为INFO,表示只有INFO级别及以上的会打印
 log.setLevel(logging.INFO)

 # 日志接口,用户只需调用这里的接口即可,这里只定位了INFO, WARNING, ERROR三个级别的日志,可根据需要定义更多接口
 @classmethod
 def info(cls, msg):
  cls.log.info(msg)
  return

 @classmethod
 def warning(cls, msg):
  cls.log.warning(msg)
  return
 @classmethod
 def error(cls, msg):
  cls.log.error(msg)
  return

est enregistré Le chemin dépend de vous.
<?xml version="1.0" encoding="utf-8"?>

<config>
 <!-- 日志保存路径 -->
 <logpath>/Users/litao/Desktop/mail_html/Log</logpath>

 <!-- 每个脚本对应的日志文件大小,单位MB -->
 <logsize>8</logsize>

 <!-- 每个脚本保存的日志文件个数 -->
 <lognum>100</lognum>
</config>

Comment utiliser

erreur, remplacez simplement les informations par l'erreur
logger.info(&#39;邮件总数量【&#39;+str(len(recivers))+&#39;】&#39;)                       
logger.info(&#39;总计发送邮件数量【&#39;+str(send_num)+&#39;】&#39;)                       
logger.info(&#39;总计发送错误数量【&#39;+str(error_num)+&#39;】&#39;)                      
logger.info(&#39;成功邮箱账号集合:&#39;+&#39;,&#39;.join(send_success_account))                    
logger.info(&#39;失败邮箱账号集合:&#39;+&#39;,&#39;.join(send_failure_account))                    
logger.info(&#39;脚本结束------------------------------------------------------------------&#39;)             
logger.info(&#39;&#39;)

Exécutez le fichier principal

Fichier spam, la première chose à laquelle tout le monde pense est l'e-mail marketing ennuyeux dans la poubelle. Cependant, si le contenu de votre e-mail est bien rédigé, pouvez-vous éviter d'être bloqué ? La réponse est non, les e-mails sont bloqués à cause des machines, si c'est le cas. réalisé par une machine, il sera facile à manipuler. Premièrement, il faut d'abord connaître le principe de fonctionnement de la machine.

La plupart des e-mails classés comme spam ont deux caractéristiques : le contenu reste inchangé et l'adresse IP reste inchangée. En fait, si le contenu continue de changer et que l'adresse IP continue de changer, en théorie, cela peut éviter d'entrer dans la boîte aux lettres de spam. Mais il n’y a pas beaucoup de main-d’œuvre et de ressources matérielles pour faire cela, donc ce que nous devons faire, c’est résoudre des problèmes probabilistes.

Confusion du contenuLe contenu reste inchangé. Nous pouvons utiliser plusieurs ensembles de modèles et les imbriquer. Ce problème est facile à résoudre, mais. l'adresse IP reste inchangée, c'est un peu plus difficile. En fait, je ne l'ai pas encore résolu. La raison principale est que j'ai peur de dépenser de l'argent. Ce que je peux faire, c'est utiliser plusieurs ensembles de modèles pour empêcher le problème. contenu d'être bloqué.

D'accord, préparons d'abord 30 sujets d'e-mail et 30 ensembles de modèles de contenu d'e-mail

Apprenez-vous un exemple de code Python pour créer un script de courrier électronique automatiqueVoici comment procéder. L'avantage est que cela peut empêcher le blocage du contenu de l'e-mail. Supposons que nous envoyions un e-mail toutes les 30 secondes, aucun des e-mails dans les 20 minutes ne sera dupliqué. Nous le considérons du point de vue de l'acceptation des noms de domaine de messagerie, c'est-à-dire que si nos cibles marketing sont toutes les boîtes aux lettres QQ, alors le contenu du courrier de la même IP reçu par le serveur de boîte aux lettres de la boîte aux lettres QQ dans les 20 minutes sera différent, c'est-à-dire dans une large mesure, vous pouvez éviter d'être banni.

账户混淆

设置这么多账号是干嘛用的呢,主要还是想混淆机器,让垃圾邮件进率更低。

下面我个人经过测试,发现邮箱服务器具有的一些特性。

163邮箱

163邮箱设置了每天每个账号邮件发送的上限位50封,账号554出错重发的时间是3小时。

tom邮箱

tom邮箱每天邮件发送数量不做限制,我们也假设是50封,但是每封邮件之间的发送间隔一定要超过30秒,要不然会被短时间连接数过大报错。

sohu邮箱

业界良心,基本上没出过啥错误,一直保持着良好的发送成功率。我们也将其定位发送间隔30秒,每日上线50封。

sina邮箱

恶心的玩意儿,每次发送邮箱前需要先登录,认证手机号,每个手机号5个邮箱哈,但是效果显著,认证完毕,和sohu一样,基本没出错过。

时间混淆

有了这些基础,我们就可以知道了,我们有120个账号,30个邮件模板,每天一刻不停的发送,每封邮件之间的间隔为30秒,一天的邮件发送量在2800封左右。

我觉得一天2800封,如果有钱的话,一台ESC的费用是3元每天,独立ip哈,如果找第三方发送,一封邮件是3分钱,量大2分钱,他们是EDM的,我测试过1500封,达到率不足千分之一。也就是说,我们发送1500封,只需要1块多钱,找第三方发送,1500封怎么也得40块钱。成本是不是很低。

好的,那就来看看邮件是如何发送的吧。

邮件发送

下面我们来看下我的主文件是如何搞的

#coding=utf-8
import smtplib
import mimetypes
import time
import datetime

from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage

#引入外部文件
from Common.log import *

导入模块,以来的外部库和内部的文件

#目录主位置
_root_dir = '/Users/litao/Desktop/mail_html/'
_title_common = '愚人节'
愚人节主题礼物,也是为了以后省事,subject和内容中设计到title的均会被改为愚人节,马上愚人节了吗,营销方式,代码实现,异常方便修改。

#邮箱内容设置
_content = """\
<html>
 <style> .title{font-weight:bold;font-size:18px;}</style>
 <body>
  <p>
   <img src="cid:image1">
   <br><br>
   <span
   class="title">【愚人节】将至,您还没准备礼物?那你一定会过个开心的愚人节的</span>
   <br>
   愚人节就要来啦,礼朵朵给大伙准备了大批量的礼物伴你度过愚人节,具体百度一下【礼朵朵】,赶紧进站选礼物吧~
   <br>
   选礼物前别忘了先去心愿墙许愿哟,你的愿望可能被礼朵朵看到,可以帮你实现哟,实现的时候别忘了来礼朵朵还愿哈~
   <br><br>
   <span class="title">【礼朵朵】介绍</span>
   <br>
   国人从古至今都有送礼的习俗,送礼作为传统之一,一直流传至今,礼尚往来成为人生必修课。
   <br>
   【礼朵朵】集合商业送礼和现代送礼搭建礼物导购分享平台【朵朵礼物】,带给老少皆宜的送礼分享体验新体验。
   <br>
   与此同时,礼朵朵还给大伙准备了礼物攻略【礼物说】,让大家可以对礼物有个更全面的了解~
   <br><br>
   <span class="title">百度搜索【礼朵朵】,开启你的礼物新旅程吧~</span>
   <br><br>
  </p>
 </body>
</html> 
"""

营销内容模板,html模式实现邮件的发送,少不了有模板~

#发送邮箱smtp地址
_smtp_address = [&#39;smtp.163.com&#39;,&#39;smtp.sina.cn&#39;,&#39;smtp.tom.com&#39;,&#39;smtp.sohu.com&#39;]

smtp地址数组,用于在不同的邮件服务器间切换。

def sendMail(sender,reciver,subject,content,passwd,smtpadd):
 username=sender
 password=passwd
 msg=MIMEMultipart(&#39;related&#39;)
 msg[&#39;Subject&#39;]=subject
 #html格式
 html=content
 htm = MIMEText(html,&#39;html&#39;,&#39;utf-8&#39;)
 msg.attach(htm)
 #构造图片
 fp=open(_root_dir+&#39;Image/logo_small.png&#39;,&#39;rb&#39;)
 msgImage=MIMEImage(fp.read())
 fp.close()
 msgImage.add_header("Content-ID", "<image1>")
 msg.attach(msgImage)
 fp2=open(_root_dir+&#39;Image/yurenjie.png&#39;,&#39;rb&#39;)
 msgImage2=MIMEImage(fp2.read())
 fp2.close()
 msgImage2.add_header(&#39;Content-Disposition&#39;, &#39;attachment&#39;,
       filename="愚人节活动海报.jpg")
 msg.attach(msgImage2)
 msg[&#39;From&#39;]=sender
 msg[&#39;To&#39;]=reciver

 #发送邮件
 smtp=smtplib.SMTP()
 smtp.connect(smtpadd)
 smtp.login(username, password)
 smtp.sendmail(sender, reciver, msg.as_string())
 smtp.quit()

发邮件方法,里面有两个地方需要注意,一个是

msgImage.add_header("Content-ID", "<image1>")
msg.attach(msgImage)

将邮件模板中的image1的img标签内容替换成我们想要的图片

第二个

 fp2=open(_root_dir+&#39;Image/yurenjie.png&#39;,&#39;rb&#39;)
 msgImage2=MIMEImage(fp2.read())
 fp2.close()
 msgImage2.add_header(&#39;Content-Disposition&#39;, &#39;attachment&#39;,
       filename="愚人节活动海报.jpg")

插入附件,图片是一个海报,说起海报,强烈建议大家使用创客贴这个平台,非常好用。

下面就是发送邮件啦!!!

#发送邮件
 smtp=smtplib.SMTP()
 smtp.connect(smtpadd)
 smtp.login(username, password)
 smtp.sendmail(sender, reciver, msg.as_string())
 smtp.quit()

通用方法,将文件中的以,分割的内容以数组形式返回

#读取文件中的数据,并将使用,分割的数据变为数组
def readFileToSplit(filepath):
 file_stream = open(filepath)
 try:
  data = file_stream.read()
 finally:
  file_stream.close()
 data_split = data.split(&#39;,&#39;)
 return data_split

主方法

1、切割账号

2、切换邮件服务器

3、每发送一封邮件,休息25秒,切换账号,继续发送

4、日志记录

5、错误处理

if __name__=="__main__":
 content=_content
 # 接收人的邮箱按照每天2000封来,每天的邮箱都需要更换,文件名最后以日期为准,邮件发送量以日志为准
 recivers=readFileToSplit(_root_dir+&#39;Sendmail/mail_test.txt&#39;)
 # 把4个邮箱的账号都获取到,方便下面for循环中使用
 account_163=readFileToSplit(_root_dir+&#39;Account/account163&#39;)
 account_sina=readFileToSplit(_root_dir+&#39;Account/accountsina&#39;)
 account_tom = readFileToSplit(_root_dir+&#39;Account/accounttom&#39;)
 account_sohu = readFileToSplit(_root_dir+&#39;Account/accountsohu&#39;)

 # 获取邮件发送模板
 # 注意模板之间的切换

 #log_file_stream = open(_root_dir+&#39;log&#39;, &#39;w+&#39;)
 logger.info(&#39;&#39;)
 logger.info(&#39;脚本开始------------------------------------------------------------------&#39;)

 # 统计邮件发送量
 send_num = 0
 # 统计发送出错量
 error_num = 0
 # 统计发送失败的邮箱发送账号
 send_success_account = []
 # 统计发送成功的邮箱发送账号
 send_failure_account = []

 subject_num = len(_subject)

 # 最后统计没有发出去的邮箱号,放到下日,继续发送
 for i in range(0, len(recivers)):
  try:
   sendindex = i - error_num
   num = i % 30
   account = account_163[num].split(&#39;:&#39;)
   addindex=i%4
   subjectindex = sendindex%subject_num
   if addindex == 1:
    account=account_sina[num].split(&#39;:&#39;)
   elif addindex == 2:
    account=account_tom[num].split(&#39;:&#39;)
   elif addindex == 3:
    account=account_sohu[num].split(&#39;:&#39;)
   sender=account[0]
   passwd=account[1]
   smtpadd = _smtp_address[addindex]
   #smtpstr=str(&#39;163&#39;)
   sendMail(sender, recivers[sendindex], _subject[subjectindex], content, passwd, smtpadd)
   #print(&#39;发送账号&#39;, sender, &#39;正在发送&#39;)
   str_success_1 = &#39;发送账号【&#39;+sender+&#39;】正在发送&#39;
   logger.info(str_success_1)
   #writeLog(log_file_stream,str_success_1)
   #print(&#39;接收序号&#39;, i, recivers[i],&#39;发送成功&#39;)
   str_success_2 = &#39;接受序号【&#39;+str(i)+&#39;】【&#39;+recivers[sendindex]+&#39;】发送成功&#39;
   #writeLog(log_file_stream,str_success_2)
   logger.info(str_success_2)
   logger.info(&#39;&#39;)
   #print(&#39;&#39;)
   send_num+=1
   send_success_account.append(sender)
   time.sleep(25)
  except Exception as e:
   #print(&#39;停止于:&#39;, i, recivers[i],&#39;,发送失败&#39;)
   str_failure_1 = &#39;产生错误于:【&#39;+sender+&#39;】发送失败&#39;
   #writeLog(log_file_stream,str_failure_1)
   logger.error(str_failure_1)
   #print(e)
   str_failure_2 = str(e)
   #writeLog(log_file_stream,str_failure_2)
   logger.error(str_failure_2)
   logger.info(&#39;&#39;)
   error_num+=1
   send_failure_account.append(sender)
   #print(&#39;&#39;)
   #break
 #print(&#39;安全抵达底部&#39;)
 #writeLog(log_file_stream,&#39;脚本结束&#39;)
 set(send_success_account)
 set(send_failure_account)
 logger.info(&#39;邮件总数量【&#39;+str(len(recivers))+&#39;】&#39;)
 logger.info(&#39;总计发送邮件数量【&#39;+str(send_num)+&#39;】&#39;)
 logger.info(&#39;总计发送错误数量【&#39;+str(error_num)+&#39;】&#39;)
 logger.info(&#39;成功邮箱账号集合:&#39;+&#39;,&#39;.join(send_success_account))
 logger.info(&#39;失败邮箱账号集合:&#39;+&#39;,&#39;.join(send_failure_account))
 logger.info(&#39;脚本结束------------------------------------------------------------------&#39;)
 logger.info(&#39;&#39;)
 #log_file_stream.close()

代码就这么多,至于subject邮件主题和模板怎么搞,可以自由发挥哈,可以放在主执行文件中,也可以放到配置文件中,实现可以配置,这里就不再赘述啦

开工

下面就可以开工啦,直接到项目主目录

#python mail_html.py

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn