I used Python to make a mailbox bomber to send e-mail to the finance. Unexpectedly, she chased me and shouted six

A project in recent work has the requirement to automatically send some information emails to the specified mailbox, so ...
Send mail automatically
summary

A project in recent work has the requirement to automatically send some information emails to the specified mailbox, so how to use Python to realize the function of automatically sending emails? Next, let's simply say.


Send mail using Python SMTP


SMTP (Simple Mail Transfer Protocol) is the simple mail transfer protocol. In other words, it is the protocol for sending mail. python's smplib library simply encapsulates the SMTP protocol and provides support for SMTP. It can send plain text mail, HTML files and mail with attachments.
First, we build a SendEmailManager class, which follows the idea of object-oriented programming. The general structure is as follows:

class SendEmailManager(object): def __init__(self, **kwargs): # Initialization parameters ... def _get_conf(self, key): # Get configuration parameters ... def _init_conf(self): # Initialize configuration parameters ... def _login_email(self): # Log in to the mailbox server ... def _make_mail_msg(self): # Building text mail objects ... def do_send_mail(self): # Mail sending ...

def __init__(self, **kwargs)

Class can be used to set object properties and give initial values, which can be parameters or fixed values. The parameter * * kwargs is to pass the dictionary of a variable keyword parameter to the function argument. Here, we mainly use the SMTP server (qq mailbox is used here), the proxy mailbox for sending mail, the client authorization password set in the mailbox Some initialization with variable parameters. The specific codes are as follows:


# SMTP server, qq mailbox is used here, and other mailboxes Baidu by themselves EMAIL_HOST = 'smtp.qq.com' # Proxy mailbox for sending mail EMAIL_HOST_USER = '[email protected]' # The client authorization password set in the mailbox. Note that this is not the mailbox password. For how to obtain the mailbox authorization code, please Baidu yourself~~~ EMAIL_HOST_PASSWORD = 'xxxxxxxxxxxxx'
def __init__(self, **kwargs): # Initialization parameters self.email_host = EMAIL_HOST self.email_host_user = EMAIL_HOST_USER self.email_host_pass = EMAIL_HOST_PASSWORD self.kwargs = kwargs

def _get_conf(self, key)

It is mainly responsible for reading the value in the variable parameter self.kwargs dictionary through the key for use by other functions.

def _get_conf(self, key): # Get configuration parameters value = self.kwargs.get(key) if key != "attach_file_list" and (value is None or value == ''): raise Exception("configuration parameter '%s' cannot be empty" % key) return value

def _init_conf(self)

This function is mainly responsible for initializing the function_ get_ The configuration parameters returned by conf so that the next function can call the relevant configuration parameters.

def _init_conf(self): # Initialize configuration parameters print(self._get_conf('receives')) self.receives = self._get_conf('receives') self.msg_subject = self._get_conf('msg_subject') self.msg_content = self._get_conf('msg_content') self.msg_from = self._get_conf('msg_from') # attachment self.attach_file_list = self._get_conf('attach_file_list')

def _login_email(self)

Log in to the mail server. I log in to the qq mailbox server with the port number of 465. Please Baidu for other mailbox port numbers. The code is as follows:

def _login_email(self): # Log in to the mailbox server try: server = smtplib.SMTP_SSL(self.email_host, port=465) # set_ Debug level (1) can print out all information interacting with SMTP server server.set_debuglevel(1) # Login mailbox server.login(self.email_host_user, self.email_host_pass) return server except Exception as e: print("mail login exception:", e) raise e

def _make_mail_msg(self)

The function is to build a mail instance object to process the contents of the mail. A normal e-mail generally has sender and receiver information, e-mail subject and e-mail body. Some e-mails are also attached with attachments. See the following codes for specific settings:

def _make_mail_msg(self): # Building mail objects msg = MIMEMultipart() msg.attach(MIMEText(self.msg_content, 'plain', 'utf-8')) # Mail subject msg['Subject'] = Header(self.msg_subject, "utf-8") # Sender mailbox information msg['From'] = "<%s>" % self.msg_from # msg['From'] = Header(self.msg_from + "<%s>" % self.email_host_user, "utf-8") msg['To'] = ",".join(self.receives) print("---", self.attach_file_list) if self.attach_file_list: for i, att in enumerate(self.attach_file_list): # Construct attachments and transfer files in the current directory if not att: break att_i = MIMEText(open(att, 'rb').read(), 'base64', 'utf-8') att_i["Content-Type"] = 'application/octet-stream' # The filename here can be written arbitrarily. What name is written and what name is displayed in the email att_i["Content-Disposition"] = 'attachment; filename="%s"' % att msg.attach(att_i) return msg

def do_send_mail(self)

Sending e-mail is to string the above functions and directly write the code:

def do_send_mail(self): # Mail sending try: self._init_conf() server = self._login_email() msg = self._make_mail_msg() server.sendmail(self.email_host_user, self.receives, msg.as_string()) server.close() print("Sending succeeded!") except Exception as e: print("Mail sending exception", e)

Configure parameters to test whether mail can be sent normally:

if __name__ == "__main__": mail_conf = { 'msg_from': '****@foxmail.com', # Mail sender's address 'receives': ['****@qq.com',], # The address of the mail recipient. This is a list because there may be more than one mail recipient 'msg_subject': 'Python Send mail test', # Subject of the message 'msg_content': 'hello', # Content of the message 'attach_file_list': {"test.py": "test.py", "test.txt": "./test.txt"}, # It is a list of attachment file paths, or it may not be available } manager = SendEmailManager(**mail_conf) manager.do_send_mail()

ok, it's ok to send successfully and add attachments. Now that we have realized sending mail using Python, how to automatically send mail? Next, let's talk about it.

Send mail automatically

1. Code hard coding implementation

It is to loop in the code, add an if judgment, and send every 1 hour. The code is as follows:

def delayed_sending(manager): # The parameter manager is the SendEmailManager object begin_time = int(time.time()) while True: end_time = int(time.time()) if end_time - begin_time == 1*60*60: threading.Thread(target=manager.do_send_mail()).start() begin_time = end_time print("Sent...")

At the same time, in order to prevent blocking the normal operation of the program for unknown reasons, multithreading is added to realize asynchronous mail sending. In this way, the program will send an email to the specified mailbox every hour after execution. As long as the program does not stop, the mail will continue to be sent!!

Suppose we need to send an email to the designated mailbox at 8 o'clock every day, you can do this:

def delayed_sending(manager): # The parameter manager is the SendEmailManager object hour = 8 minute = 0 second = 0 while True: now = datetime.datetime.now() if now.hour == hour and now.minute == minute and now.second == second: threading.Thread(target=manager.do_send_mail()).start() print("Sent...")

Although the functions of the above two methods have been realized, the implementation method is really low!

2. The timing function is realized through the module

In addition to hard coding, we can also implement it through the schedule module of task timing runtime in python:

# schedule module using python task timing runtime def send_mail_by_schedule(manager): schedule.every(20).minutes.do(manager.do_send_mail) # Every 20 minutes schedule.every().hour.do(manager.do_send_mail) # Every hour schedule.every().day.at("10:00").do(manager.do_send_mail) # Once every day at 10:00 schedule.every().monday.do(manager.do_send_mail) # Once a week on Monday schedule.every().friday.at("21:00").do(manager.do_send_mail) # Every Friday at 21:00 while True: schedule.run_pending() time.sleep(1)

Schedule is actually just a timer. In the while True loop, schedule.run_pending() is to keep the schedule running all the time to query the above pile of tasks. In the tasks, you can set different times to run. This is similar to crontab.

However, if multiple scheduled tasks are running, they are actually executed one by one from top to bottom in order. If the above tasks are complex and time-consuming, the running time of the following tasks will be affected. If you run 5 tasks every 2 minutes, each task takes 1 minute, which is a total of 5 minutes. In this way, when the next 2 minutes arrive, the task of the previous round is still running, and then a new round of tasks is started. The solution is also simple: use multithreading / multiprocessing.


def run_threaded(manager): threading.Thread(target=manager.do_send_mail()).start() # schedule module using python task timing runtime def send_mail_by_schedule(manager): schedule.every(1).minutes.do(run_threaded, manager) # Every 20 minutes schedule.every().hour.do(run_threaded, manager) # Every hour schedule.every().day.at("10:00").do(run_threaded, manager) # Once every day at 10:00 schedule.every().monday.do(run_threaded, manager) # Once a week on Monday schedule.every().friday.at("21:00").do(run_threaded, manager) # Every Friday at 21:00 while True: schedule.run_pending() time.sleep(1)

In this way, we can create a thread for each scheduled task and let the task run in the thread, so as to achieve the effect of multiple tasks working in parallel. Is this method more time-saving and labor-saving than the first one, and it doesn't need a lot of code at all. It's perfect!

summary

In fact, to put it bluntly, the most important thing to automatically send e-mail is to realize the automatic execution of tasks, so there are many implementation schemes. For example, you can also use asynchronous task scheduler like celery to listen to the queue to realize the automatic execution of tasks, etc.

After completing the automatic e-mail, we can also let the program send us weather forecast, daily news, chicken soup and so on every day (you can also send it to boyfriend and girlfriend) hahaha.


16 November 2021, 06:12 | Views: 8994

Add new comment

For adding a comment, please log in
or create account

0 comments