Recently, many communication tools have been used, such as corporate WeChat robots, pins, WeChat public number interfaces (unauthenticated subscription public numbers), which are too weak for mail.There are no richer versions, for example.Of course, it doesn't mean that the better the presentation, the better the appointment, which depends on personal circumstances, but I just need a richer presentation, and eventually I returned to the mail, which is really fragrant!
And I don't have the right microsignal to log on to the interface of personal microsignal. If the web version of the WeChat is not enveloped, I think this is the best way to combine presentation with message timeliness.
Environmental Science
Although it's easy to be compatible with Python2 and Python3 just by sending an email, hug Python3. I don't have a compatible way to write python2 here, so I need python3 or more.
Format of mail
Mail is in two main formats: plain and html
plain is like normal text, no formatting.
As its name implies, html is in HTML format, which is equivalent to a message being a static web page. This makes it very playable. You can control the presentation through css.
Note: Although the css syntax here is the same, it is not certain whether it will exactly match the browser rendering results.
Then someone might ask, what do I do with a dynamic web page? Send a link?
Mailbox account
Whether it is QQ mailbox or NetEase mailbox, there is no problem. The important thing is that there is an account name and password that can send mail through the smtp server, everybody Baidu here.
Code to send mail
Because the code to send the mail is the same in each of the following steps, the line is pasted out
def send_email(msg, mail_to, smtp_host, smtp_username, smtp_password, subject, from_): msg["Subject"] = Header(subject, "utf-8") msg["From"] = Header(from_, "utf-8") if not isinstance(mail_to, list): mail_to = [mail_to] msg["To"] = COMMASPACE.join(mail_to) try: print("Preparing to connect smtp Mail Server: %s" % smtp_host) client = smtplib.SMTP(smtp_host) print("Connection Successful") # client = smtplib.SMTP("localhost") # client.set_debuglevel(1) # print(self.mail_user, self.mail_pass) client.login(smtp_username, smtp_password) print("Login Successful") # print("=====>", self.mail_from, mail_to) print("Through Mailbox[%s]Send mail to %s" % (smtp_username, COMMASPACE.join(mail_to))) client.sendmail(smtp_username, mail_to, msg.as_string()) print("Send Successfully...") return True except Exception: print("Failed to send mail") finally: client.quit()
If you have problems sending mail, you canClient.set_The comment for debug level (1) is cancelled, which shows enough debug information to troubleshoot the problem.
Send local pictures
Sending pictures here means that pictures are embedded in the mail instead of appearing as attachments.
The results are as follows:
The code is as follows:
EMAIL_IMAGE_TEMPLATE = """<html> <head> <title>Page Title</title> </head> <body> <h3>This is a picture</h3> <p><img src="cid:{{image_name}}" height="112" width="200" ></p> </body> </html> """ def create_image_eamil_contant(fp): tpl = Template(EMAIL_IMAGE_TEMPLATE) if not path.exists(fp): sys.exit("The map to be sent does not exist") msg = MIMEMultipart("related") image_name = "demo" with open(fp, "rb") as rf: mime_image = MIMEImage(rf.read()) # Note: parentheses must be <> mime_image.add_header("Content-ID", "<%s>" % image_name) msg.attach(mime_image) # Render mail text content text = tpl.render(image_name=image_name) msg_alternative = MIMEMultipart("alternative") msg_alternative.attach(MIMEText(text, "html", "utf-8")) msg.attach(msg_alternative) return msg
If you've used python's web framework, you must be familiar with rendering text, because most web frameworks support text rendering, which is jinja2 used here.
Send program generated photos
Actually, there is no difference between this and the above. The only difference is whether to save it locally. Since I can send a local picture, will I save it locally and then follow the above method soon? First of all, this method is OK, but with one more IO, why should I put the things that can be solved in memory locally?
This is mainly the case when the picture is returned from another interface or when it is generated in real time.It's easy, but it's interesting to talk about it.
The simulation here is based on the assumption that multiple base64-encoded pictures are captured online and need to be grouped together and sent directly without saving locally.
This base64-encoded picture has been saved locally under the name demo_base64.txt
The results are as follows:
The code is as follows:
EMAIL_ONLINE_IMAGE_TEMPLATE = """<html> <head> <title>Page Title</title> </head> <body> <h3>This is a picture</h3> <p><img src="cid:{{image_name}}" ></p> </body> </html> """ def create_online_image_content(): from PIL import Image tpl = Template(EMAIL_ONLINE_IMAGE_TEMPLATE) fp = "demo_base64.txt" if not path.exists(fp): sys.exit("To send base64 Coded picture does not exist") msg = MIMEMultipart("related") image_name = "demo" with open(fp, "rb") as rf: base64_data = rf.read() img_data = base64.b64decode(base64_data) # Because the open method requires a file-like file object, and the object type we decoded is the bytes type # The bytes type does not have a read, close method for file objects, so we need to wrap it around with a BytesIO object, which returns a file-like file object img = Image.open(BytesIO(img_data)) img_width, img_height = img.size repeat_times = 5 # compose images ret_img = Image.new(img.mode, (img_width, img_height * repeat_times)) for index in range(repeat_times): ret_img.paste(img, box=(0, index * img_height)) # Because MIMEImage requires a bytes object, we need to get the binary data encoded by the picture instead of the array data of the picture img_bytes = BytesIO() # If you do not specify a picture format, you will get an error because you do not have a file name ret_img.save(img_bytes, "png") mime_image = MIMEImage(img_bytes.getvalue()) # Note: parentheses must be <> mime_image.add_header("Content-ID", "<%s>" % image_name) msg.attach(mime_image) # Render mail text content text = tpl.render(image_name=image_name) msg_alternative = MIMEMultipart("alternative") msg_alternative.attach(MIMEText(text, "html", "utf-8")) msg.attach(msg_alternative) return msg
One interesting point here is that BytesIO is used to simulate a file-like object.PIL needs to be installed here
Send a Styled Static Web Page
The previous code sufficiently illustrates what happened to the picture, as demonstrated by a css-style table
The results are as follows:
The code is as follows:
EMAIL_TEMPLATE = """<html> <head> <style type="text/css"> table { border-collapse: collapse; margin: 0 auto; text-align: center; } table td, table th { border: 1px solid #cad9ea; color: #666; height: 30px; } table thead th { background-color: #CCE8EB; width: 100px; } table tr:nth-child(odd) { background: #fff; } table tr:nth-child(even) { background: #F5FAFA; } </style> </head> <body> <p>There are a total of the following{{record_size}}Bar data</p> <table width="90%" class="table"> <thead> <tr> {% for label in labels %} <th>{{label}}</th> {% endfor %} </tr> </thead> <tbody> {% for item in items %} <tr> {% for value in item %} <td>{{value}}</td> {% endfor %} </tr> {% endfor %} </tbody> </table> </html>""" def create_html_content(): tpl = Template(EMAIL_TEMPLATE) record_size = 10 label_size = 5 labels = ["label-%s" % i for i in range(label_size)] items = [] for _ in range(record_size): item = ["item-%s" % value_index for value_index in range(label_size)] items.append(item) text = tpl.render(record_size=record_size, items=items, labels=labels) msg = MIMEText(text, "html", "utf-8") return msg
Source code address
https://github.com/youerning/blog/tree/master/sendmail
If you're looking forward to future articles, you can focus on my WeChat Public Number (Ear Notes), Headline Number (Ear Notes), github.
Postnote
It's also a good way to send an attachment, such as a generated PDF, which is a great file format.But PDF is not used for the time being, so I'll have a chance to talk about it later.Finally, it should be noted that the display effect on the mobile phone side is different from that on the web page of the computer.