Last active
October 2, 2017 12:30
-
-
Save jgsogo/e3f7faf6ad19721d4c7b6393f65f7fec to your computer and use it in GitHub Desktop.
Send mass mail using GMail
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import sys | |
import logging | |
from send_mail import gmail_send | |
log = logging.getLogger(__name__) | |
_LOG_LEVEL_STRINGS = ['CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG'] | |
def read_data(filename, headers): | |
def dequote(s): | |
if (s[0] == s[-1]) and s.startswith(("'", '"')): | |
return s[1:-1] | |
return s | |
ret = [] | |
with open(filename, 'r') as f: | |
for line in f.readlines(): | |
if line.startswith("#") or not len(line.strip()): continue | |
data = [dequote(item.strip()) for item in line.split(',')] | |
if len(data) != len(headers): | |
log.warning("Line discarded. Fields do not match with headers: {!r}".format(line)) | |
ret.append({key: value for key, value in zip(headers, data)}) | |
return ret | |
def generate_pdf(params, output_filename): | |
# TODO: implement a more flexible way to doy it | |
log.debug(" - Generate PDF to {}".format(output_filename)) | |
return output_filename | |
def send_mail(address, attachment): | |
log.debug(" - Send email to {}".format(address)) | |
subject = "Prueba batch" # TODO: Whatever... | |
text = "Contenido del mensaje" # TODO: More blablabla | |
gmail_send([address], subject, text, attachments=[attachment]) | |
return False | |
def _log_level_string_to_int(log_level_string): | |
if not log_level_string in _LOG_LEVEL_STRINGS: | |
message = 'invalid choice: {0} (choose from {1})'.format(log_level_string, _LOG_LEVEL_STRINGS) | |
raise argparse.ArgumentTypeError(message) | |
log_level_int = getattr(logging, log_level_string, logging.INFO) | |
# check the logging log_level_choices have not changed from our expected values | |
assert isinstance(log_level_int, int) | |
return log_level_int | |
if __name__ == '__main__': | |
import argparse | |
GENERATE = ['generate-pdf', 'generate-and-send'] | |
SEND = ['send-pdf', 'generate-and-send'] | |
ACTIONS = set(GENERATE + SEND) | |
me_path = os.path.dirname(__file__) | |
tmp_path_default = os.path.abspath(os.path.join(me_path, 'tmp')) | |
parser = argparse.ArgumentParser(description='So we are to spam ^^') | |
parser.add_argument('--action', choices=ACTIONS, required=True) | |
parser.add_argument('--data-file', dest='data_file', required=True) | |
parser.add_argument('--log-level', default='INFO', dest='log_level', | |
type=_log_level_string_to_int, nargs='?', | |
help='Set the logging output level. {0}'.format(_LOG_LEVEL_STRINGS)) | |
parser.add_argument('--tmp-dir', dest='tmp_dir', default=tmp_path_default) | |
args = parser.parse_args() | |
# Configure log | |
ch = logging.StreamHandler() | |
ch.setLevel(args.log_level) | |
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)7s - %(message)s') | |
ch.setFormatter(formatter) | |
root_logger = logging.getLogger() | |
root_logger.addHandler(ch) | |
root_logger.setLevel(args.log_level) | |
sys.stdout.write("="*20) | |
sys.stdout.write("\nSEND MASS MAIL WITH ATTACHMENT\n") | |
sys.stdout.write("\n + data_file: {}".format(args.data_file)) | |
sys.stdout.write("\n + action: {}".format(args.action)) | |
sys.stdout.write("\n + tmp directory: {}".format(args.tmp_dir)) | |
sys.stdout.write("\n") | |
if not os.path.exists(args.tmp_dir): | |
os.makedirs(args.tmp_dir) | |
data = read_data(args.data_file, headers=["address", "name"]) | |
total = len(data) | |
i = 1 | |
sys.stdout.write("\nWork over {} lines".format(total)) | |
for it in data: | |
sys.stdout.write("\n[{}/{}] {}".format(i, total, it['name'])) | |
sys.stdout.flush() | |
valid_filename = "".join(x for x in it['address'] if x.isalnum()) | |
valid_filename = valid_filename + '.pdf' | |
pdf_filename = os.path.join(args.tmp_dir, valid_filename) | |
if args.action in GENERATE: | |
sys.stdout.write(" > generating") | |
sys.stdout.flush() | |
generate_pdf(it, pdf_filename) | |
if args.action in SEND: | |
sys.stdout.write(" > sending") | |
sys.stdout.flush() | |
send_mail(it['address'], pdf_filename) | |
i = i+1 | |
sys.stdout.write("\n Done! \n") | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
import os | |
import smtplib | |
from email import encoders | |
from email.mime.base import MIMEBase | |
from email.mime.multipart import MIMEMultipart | |
from email.mime.text import MIMEText | |
import logging | |
log = logging.getLogger(__name__) | |
try: | |
SENDER = os.environ['MASS_MAIL_SENDER'] | |
PASSWORD = os.environ['MASS_MAIL_PASSWORD'] | |
except KeyError as e: | |
sys.stderr.write("Add environment variables 'MASS_MAIL_SENDER' and 'MASS_MAIL_PASSWORD'." | |
"Use something like the following in your console:" | |
"$export MASS_MAIL_SENDER=mymail@gmail.com\n") | |
exit() | |
def gmail_send(to, subject, text, attachments=[]): | |
assert type(to)==list | |
assert type(attachments)==list | |
# Create the enclosing (outer) message | |
outer = MIMEMultipart() | |
outer['Subject'] = subject | |
outer['To'] = ', '.join(to) | |
outer['From'] = SENDER | |
outer.preamble = 'You will not see this in a MIME-aware mail reader.\n' | |
outer.attach(MIMEText(text, 'plain')) # or 'html' | |
# Add the attachments to the message | |
for file in attachments: | |
try: | |
with open(file, 'rb') as fp: | |
msg = MIMEBase('application', "octet-stream") | |
msg.set_payload(fp.read()) | |
encoders.encode_base64(msg) | |
msg.add_header('Content-Disposition', 'attachment', filename=os.path.basename(file)) | |
outer.attach(msg) | |
except: | |
print("Unable to open one of the attachments. Error: ", sys.exc_info()[0]) | |
raise | |
composed = outer.as_string() | |
# Send the email | |
try: | |
with smtplib.SMTP_SSL('smtp.googlemail.com', 465) as s: | |
s.login(SENDER, PASSWORD) | |
s.sendmail(SENDER, to, composed) | |
s.close() | |
log.debug("Email sent!") | |
except smtplib.SMTPAuthenticationError as e: | |
sys.stderr.write("\n\nERROR! Your password is wrong or you need to allow 'less secure apps' in " | |
"your GMail account (+info. https://support.google.com/accounts/answer/6010255?hl=en)\n\n") | |
exit() | |
except: | |
print("Unable to send the email. Error: ", sys.exc_info()[0]) | |
raise |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
To run this would we need both codes in the google sheet?