Heim  >  Artikel  >  Backend-Entwicklung  >  Bringen Sie Ihnen ein Python-Codebeispiel bei, um ein automatisches E-Mail-Skript zu erstellen

Bringen Sie Ihnen ein Python-Codebeispiel bei, um ein automatisches E-Mail-Skript zu erstellen

Y2J
Y2JOriginal
2017-04-27 11:58:462812Durchsuche

In diesem Artikel werden hauptsächlich die relevanten Kenntnisse des automatischen E-Mail-Skripts von Python vorgestellt. Es hat einen sehr guten Referenzwert. Schauen wir es uns mit dem Editor unten an

Origin

Während dieser Zeit habe ich ein Skript zum Versenden von Gruppen-E-Mails erstellt Um zu verhindern, dass ich Spam bekomme, habe ich es gerade geschafft und die Spam-Eintrittsrate liegt bei 50 %, was meiner Meinung nach nicht schlecht ist. Ich werde wahrscheinlich Geld ausgeben müssen, um einen Host zu kaufen, ihn zunächst einen Monat lang zu starten, die Wirkung zu sehen und ihn dann zu erweitern.

Das Skript ist hauptsächlich in Python geschrieben und wird von der smtplib-Bibliothek angepasst. Heute werde ich Ihnen hauptsächlich erklären, wie Sie den Zugriff auf das Spam-System vermeiden können um das gesamte System aufzubauen. Vielleicht habe ich gerade erst mit Python begonnen und es gibt viele mögliche falsche Schreibweisen~

Konfiguration

CentOS7.0-System

Python 3.4

Die Standardversion unter CentOS 7.0 ist Python 2.7.5. Aktualisieren wir zuerst die Python-Version

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

Laden Sie die Python 3.4-Version herunter

#tar -xf Python-3.4.3.tgz
#cd Python-3.4.3/
#./configure

Bei der Konfiguration hier stellen Sie möglicherweise fest, dass in Ihrer Umgebung die gcc-Kompilierungsumgebung nicht installiert ist. Führen Sie die folgende Anweisung aus und konfigurieren Sie dann

#yum -y install gcc
#yum -y install gdb
#yum -y install gcc-c++

Kompilieren und installieren

#make
#make install

Da yum nach dem Ersetzen der Python-Version möglicherweise nicht richtig funktioniert, müssen zwei Dateien geändert werden

#vim /usr/bin/yum
#vim /usr/libexec/urlgrabber-ext-down

Ändern Sie #!/usr/bin/python im Header dieser beiden Dateien zu #!/usr /bin/python2.7, speichern und beenden, yum wird wiederbelebt, wenn es voll ist

Stellen Sie nach dem Kompilieren Python3.4 als Standard-Python-Analyse ein.

#ln -s /usr/local/bin/python3.4 /usr/bin/python

Überprüfen Sie die Python-Version, nachdem der Link abgeschlossen ist

#python -V

Wenn Python3.4 angezeigt wird, wird die Version angezeigt Der Wechsel ist abgeschlossen

Systemarchitektur

Bringen Sie Ihnen ein Python-Codebeispiel bei, um ein automatisches E-Mail-Skript zu erstellen

Konto: Das Verzeichnis, in dem das E-Mail-Konto des Absenders, meine 163-E-Mail und Sina-E-Mail gespeichert werden , Sohu-E-Mail und Tom-E-Mail sind alles, was ich bei Taobao gekauft habe, um SMTP-Dienste zu senden. Sie können sie für weniger als die Kosten einer Mahlzeit erhalten. Das Kontokennwort wird durch [:] getrennt, und jedes Konto wird durch [ getrennt. ,].

Common: Referenzklassenordner, der die Rinzhi-Systemkonfigurationsdatei und den Quellcode des Protokollsystems enthält

Conf: Globale Konfigurationsdatei, derzeit nicht nützlich

Bild: Bildressourcen, die müssen beim Versenden von E-Mails verwendet werden

Protokoll: Protokolldateien, unterschieden nach Datum

Protokollsicherungen: Protokollsicherungsdateien, die zum Sichern abgelaufener Protokolle verwendet werden

Sendmail: Verwenden Sie zum Speichern der E-Mail-Informationen des Empfängers [,], um die Konten zu trennen

mail_html.py: Hauptausführungsskript

README.md: Benutzeranweisungen für die Git-Versionskontrolle, ich verwende den Code The Cloud verwaltet meinen Code

Protokollsystem

Wenn es um Skriptsysteme geht, spielen Protokolle eine sehr wichtige Rolle, insbesondere wenn Ihr Skript schief geht und Sie überprüfen müssen, wann Es ist falsch, es ist sehr wichtig. Ich habe auch einen Code für das Log-Protokollierungssystem aus dem Internet erhalten. Ich denke, er ist sehr nützlich und für jedermanns Referenz. Die Hauptidee besteht darin, das Protokoll auszudrucken Wenn ich zum Bildschirm komme, werde ich nichts anderes sagen. Da er online ist, stelle ich ihn ein Die Konfigurationsdatei des Protokollsystems

wird gespeichert. Der Weg liegt bei Ihnen.
# 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

So verwenden Sie

<?xml version="1.0" encoding="utf-8"?>

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

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

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

Fehler, ersetzen Sie einfach die Informationen durch Fehler

Führen Sie die Hauptdatei aus
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;)

Datei-Spam, Das erste, woran jeder denkt, ist die lästige Marketing-E-Mail im Papierkorb. Wenn Ihr E-Mail-Inhalt jedoch gut geschrieben ist, können Sie verhindern, dass E-Mails von Maschinen blockiert werden Maschine, es wird einfach zu handhaben sein. Zuerst müssen wir das Funktionsprinzip der Maschine kennen.

Die meisten als Spam eingestuften E-Mails weisen zwei Merkmale auf: Der Inhalt bleibt unverändert und die IP bleibt unverändert. Wenn sich der Inhalt und die IP ständig ändern, kann theoretisch vermieden werden, dass sie in das Spam-Postfach gelangen. Dafür stehen jedoch nicht so viele Arbeitskräfte und materielle Ressourcen zur Verfügung. Wir müssen also probabilistische Probleme lösen.

Inhaltliche Verwirrung

Der Inhalt bleibt unverändert. Dieses Problem ist jedoch leicht zu lösen Die IP bleibt unverändert, das ist tatsächlich etwas schwieriger. Der Hauptgrund ist, dass ich Angst habe, mehrere Vorlagen zu verwenden, um das zu verhindern dass Inhalte nicht blockiert werden. Okay, bereiten wir zunächst 30 E-Mail-Betreffs und 30 Sätze von E-Mail-Inhaltsvorlagen vor

So wird es gemacht Der Vorteil besteht darin, dass verhindert werden kann, dass der Inhalt der E-Mail blockiert wird. Angenommen, wir senden alle 30 Sekunden eine E-Mail, dann wird keine der E-Mails innerhalb von 20 Minuten dupliziert. Wir betrachten dies aus der Perspektive der Akzeptanz von E-Mail-Domänennamen. Das heißt, wenn unsere Marketingziele alle QQ-Postfächer sind, ist der E-Mail-Inhalt derselben IP, der innerhalb von 20 Minuten vom Postfachserver des QQ-Postfachs empfangen wird, unterschiedlich Ein Verbot kann weitgehend vermieden werden.

账户混淆

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

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

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

Das obige ist der detaillierte Inhalt vonBringen Sie Ihnen ein Python-Codebeispiel bei, um ein automatisches E-Mail-Skript zu erstellen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn