Using SMTP and the Gmail API (Could you please demonstrate both methods?), I need to send thousands of emails, each customized according to a name and containing an attachment. How can I accomplish this process as quickly and efficiently as possible?
My current method, in its simplest form, is as follows:
from os import path
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from traceback import print_exc
from copy import deepcopy
from importlib import util
from time import perf_counter
class EmailSender:
def __init__(self, username, client, data, message, subject, html, attachments):
# Constructor details...
def send_email(self, index, receivers, message):
try:
# Sending email details...
except Exception as e:
print_exc()
def prepare_and_send_emails(self):
for index, i in self.data.items():
tmp_msg = deepcopy(self.message)
self.send_email(index, i, tmp_msg)
@staticmethod
def multi_replace(string, replacements):
# Multi-replace function...
def call_func(script_path, func=None, arguments=None):
# Function to call external scripts...
time = perf_counter()
client = smtplib.SMTP('smtp.gmail.com', 587)
client.starttls()
client.login('[email protected]', 'rvfc twfa xzve yxah')
data = {0: ['[email protected]', [100], {'Name': 'Johan'}], 1: ['[email protected]', [100], {'Name': 'Max'}],
# Data dictionary...
message = MIMEMultipart()
subject = "Mail to ${Name}"
html = "Hello Dear ${Name}"
attachments = { # Attachment details... }
non_script_attachments = [key for key, value in attachments.items() if not value['script_name']]
script_attachments = {key: value for key, value in attachments.items() if value["script_name"]}
# Attachment handling...
sender = EmailSender('[email protected]', client, data, message, subject, html, script_attachments)
sender.prepare_and_send_emails()
print(perf_counter()-time)
But this is so slow. When I use threads like this:
def prepare_and_send_emails(self):
threads = []
for index, i in self.data.items():
tmp_msg = deepcopy(self.message)
thread = threading.Thread(target=self.send_email, args=(index, i, tmp_msg))
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
I encounter various errors. I used similar code within Google, and it gave errors when using threads there too.
When I try open new SMTP server for each thread this is even more slower than normal code.
How can I use something like threads for sending emails?