import configparser from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from smtplib import SMTP_SSL from argparse import ArgumentParser from datetime import date, timedelta import wikiquote from src.event import create_events_from_span week_days = ['Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi', 'Dimanche'] months = ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'] class DataPaths: def __init__(self, mariages_path, members_path): self._mariages_path = mariages_path self._members_path = members_path def mariages(self): return self._mariages_path def members(self): return self._members_path class Mailer: def __init__(self, server, user, password): self._server = server self._usr = user self._pwd = password def server(self): return self._server def user(self): return self._usr def password(self): return self._pwd class EmailSender: def __init__(self, mailer: Mailer, paths: DataPaths, receiver: str): self._mailer = mailer self._paths = paths self._receiver = receiver print("Email Sender is set up") def send_paturlettre(self): msg = MIMEMultipart('alternative') msg['Subject'] = f'[Paturlettre] Semaine {get_week_number_and_span()[0]}' msg['From'] = 'Paturlettre ' msg['To'] = 'Diffusion Paturlettre ' msg.preamble = f'La Paturlettre de la semaine {get_week_number_and_span()[0]} !' print("Msg Header is set up") events_previous, events_current, events_next = get_events(self._paths) msg.attach(MIMEText(create_plain_email(events_previous, events_current, events_next), 'plain')) msg.attach(MIMEText(create_html_templated(events_previous, events_current, events_next), 'html')) print("Msg body is generated") conn = SMTP_SSL(self._mailer.server(), port=465) print("SMTP Connection OK") conn.login(self._mailer.user(), self._mailer.password()) print("SMTP Login OK") try: print("Sending to {}".format(self._receiver)) conn.sendmail(msg['From'], self._receiver, msg.as_string()) print("Paturlettre has been sent!") finally: conn.quit() def create_html_templated(events_previous, events_current, events_next): with open('../html_template/mail.html', 'r', encoding='utf-8') as tmp: mail = tmp.read() mail = mail.replace('{LogoAddress}', 'https://tof.cx/images/2020/05/27/448fd7d507778064b39ba95c381cd3e8.png') wk_and_span = get_week_number_and_span() mail = mail.replace('{Main_Title}', f'Semaine {wk_and_span[0]}') mail = mail.replace('{Sub_Title}', f'du {wk_and_span[1].day} {months[wk_and_span[1].month - 1]}' f' au {wk_and_span[2].day} {months[wk_and_span[2].month - 1]}') mail = mail.replace('{EVENTS_PREVIOUS}', create_html_string_for_week(events_previous)) mail = mail.replace('{EVENTS_CURRENT}', create_html_string_for_week(events_current)) mail = mail.replace('{EVENTS_NEXT}', create_html_string_for_week(events_next)) quote = wikiquote.qotd(lang='fr') mail = mail.replace('{Quote_Text}', quote[0]) mail = mail.replace('{Quote_Author}', quote[1]) return mail def create_plain_email(events_previous, events_current, events_next): wk_and_span = get_week_number_and_span() mail_plain = f'Paturlettre - Semaine {wk_and_span[0]}\n' mail_plain += f'du {wk_and_span[1].day} {months[wk_and_span[1].month - 1]}' \ f' au {wk_and_span[2].day} {months[wk_and_span[2].month - 1]}\n' mail_plain += '\n\n' mail_plain += 'Semaine précédente :\n' mail_plain += create_plain_string_for_week(events_previous) mail_plain += '\n' mail_plain += 'Cette semaine :\n' mail_plain += create_plain_string_for_week(events_current) mail_plain += '\n' mail_plain += 'Semaine suivante :\n' mail_plain += create_plain_string_for_week(events_next) mail_plain += '\n\n' quote = wikiquote.qotd(lang='fr') mail_plain += 'Citation de la semaine :\n' mail_plain += quote[0] + '\n' mail_plain += f'— {quote[1]}\n\n' mail_plain += 'Cet email vous est envoyé par Cyril NOVEL parce que vous êtes inscrit sur la ' \ 'liste de diffusion de la Paturlettre.\n' mail_plain += 'Des questions ou des commentaires ? Envoyez un email à paturlettre@kosmon.fr\n' return mail_plain def create_html_string_for_day(day_name: str, events: list, last_day: bool) -> str: html_str = ' \n' html_str += f' {day_name}\n' html_str += ' \n' for i in range(0, len(events)): e = events[i] style = "width: 100%;" if not last_day and i == len(events) - 1: style = "width: 100%; border-bottom: 1px dashed #9ba5ae;" html_str += f' \n' html_str += f' ' \ f'{e.type_str()} · {e.event_date_as_str()} ' \ f'
{e.event_description()}\n' html_str += ' ' return html_str def create_html_string_for_no_event() -> str: html_str = ' \n' html_str += f' Pas d\'événements\n' html_str += ' \n' return html_str def create_plain_string_for_no_event() -> str: return 'Pas d\'événements\n' def create_html_string_for_week(events: list): if not events: return create_html_string_for_no_event() d = {} last_day = -1 for i in range(0, 7): d[i] = [e for e in events if e.get_actual_weekday() == i] if d[i]: last_day = i html_str = '' for i in range(0, 7): if d[i]: html_str += create_html_string_for_day(week_days[i], d[i], i == last_day) return html_str def create_plain_string_for_week(events: list): if not events: return create_plain_string_for_no_event() plain_str = '' d = {} for i in range(0, 7): d[i] = [e for e in events if e.get_actual_weekday() == i] for i in range(0, 7): if d[i]: plain_str += f' - {week_days[i]} :\n' for e in d[i]: plain_str += f' * {e.type_str()} · {e.event_date_as_str()} · ' \ f'{e.event_description()}\n' return plain_str def get_events(data_paths: DataPaths): today = date.today() monday = today - timedelta(days=today.weekday()) previous_monday = monday - timedelta(days=7) next_monday = monday + timedelta(days=7) previous_week_events = create_events_from_span(previous_monday, previous_monday + timedelta(days=6), data_paths.members(), data_paths.mariages()) this_week_events = create_events_from_span(monday, monday + timedelta(days=6), data_paths.members(), data_paths.mariages()) next_week_events = create_events_from_span(next_monday, next_monday + timedelta(days=6), data_paths.members(), data_paths.mariages()) return previous_week_events, this_week_events, next_week_events def get_week_number_and_span(): today = date.today() monday = today - timedelta(days=today.weekday()) return today.isocalendar()[1], monday, monday + timedelta(days=6) def load_config(config_file) -> (Mailer, DataPaths, str): config = configparser.ConfigParser() config.read(config_file, encoding='utf-8') mailer = Mailer(config['Mailer']['smtp_server'], config['Mailer']['user'], config['Mailer']['password']) data_path = DataPaths(config['Data']['mariages'], config['Data']['members']) receiver = config['Destination']['receiver'] return mailer, data_path, receiver def main(): parser = ArgumentParser(description='Send Paturlettre mail') parser.add_argument('-c', '--config', dest='config', help='Config file to load') args = parser.parse_args() mailer, paths, receiver = load_config(args.config) email_sender = EmailSender(mailer, paths, receiver) email_sender.send_paturlettre() print("Exiting script") if __name__ == '__main__': main()