From 2c8793825d13bf4336c0d86de903bb50ecc51726 Mon Sep 17 00:00:00 2001 From: bernat Date: Sat, 12 Nov 2005 21:18:01 +0100 Subject: [PATCH] Fonctions pour envoi de mail. Par Stphane. darcs-hash:20051112201801-d1718-ed67c4a669692aa8d46036452171044cacfedee0.gz --- gestion/email_tools.py | 130 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100755 gestion/email_tools.py diff --git a/gestion/email_tools.py b/gestion/email_tools.py new file mode 100755 index 00000000..e38c00f2 --- /dev/null +++ b/gestion/email_tools.py @@ -0,0 +1,130 @@ +#! /usr/bin/env python +# -*- coding: iso-8859-15 -*- + +# Copyright (C) Stéphane Glondu + ??? +# Licence : ??? + +""" +Envoi de mails textes encodés et bien formatés (encodages spécifiés là il faut). +Autres outils relatifs aux mails. + +format_sender et send_email adaptés depuis /usr/scripts/impression/crans_backend.py. +""" + +import re + + +def format_sender(sender, header_charset='ISO-8859-15'): + """ + Check and format sender for header. + """ + from email.Header import Header + from email.Utils import parseaddr, formataddr + + # Split real name (which is optional) and email address parts + sender_name, sender_addr = parseaddr(sender) + + # We must always pass Unicode strings to Header, otherwise it will + # use RFC 2047 encoding even on plain ASCII strings. + sender_name = str(Header(unicode(sender_name), header_charset)) + + # Make sure email addresses do not contain non-ASCII characters + sender_addr = sender_addr.encode('ascii') + + return formataddr((sender_name, sender_addr)) + + +def send_email(sender, recipient, subject, body, server='localhost', cc=None, debug=False): + """ + Send an email. + + All arguments should be Unicode strings (plain ASCII works as well). + Only the real name part of sender and recipient addresses may contain + non-ASCII characters. The email will be properly MIME encoded. + + The charset of the email will be the first one out of US-ASCII, ISO-8859-15 + and UTF-8 that can represent all the characters occurring in the email. + + Argument server maybe a string, indicating the name of the SMTP server, or + directly an instance of smtplib.SMTP. + + The resulting mail will be sent to debug if not False. + Otherwise, it will be sent to recipient and cc. + """ + from smtplib import SMTP + from email.MIMEText import MIMEText + from email.Header import Header + + # Header class is smart enough to try US-ASCII, then the charset we + # provide, then fall back to UTF-8. + header_charset = 'ISO-8859-15' + + # We must choose the body charset manually + for body_charset in 'US-ASCII', 'ISO-8859-15', 'UTF-8': + try: + body.encode(body_charset) + except UnicodeError: + pass + else: + break + + sender = format_sender(sender) + recipient = format_sender(recipient) + if cc: cc = format_sender(cc) + + # Create the message ('plain' stands for Content-Type: text/plain) + msg = MIMEText(body.encode(body_charset), 'plain', body_charset) + msg['From'] = sender + msg['To'] = recipient + msg['Subject'] = Header(unicode(subject), header_charset) + if cc: msg['Cc'] = cc + + if debug: + actual_recipient = [debug] + else: + actual_recipient = [recipient] + if cc: actual_recipient.append(cc) + + # Send the message + if isinstance(server, SMTP): + server.sendmail(sender, actual_recipient, msg.as_string()) + else: + smtp = SMTP() + smtp.connect(server) + smtp.sendmail(sender, actual_recipient, msg.as_string()) + smtp.quit() + + +def parse_mail_template(fichier): + """ + Lit fichier et renvoie le couple sujet, corps en unicode. + Les trois premières lignes de fichier doivent être : + Encoding: + Subject: + + Le reste forme le corps du mail. + L'argument fichier peut être un nom de fichier, ou directement une + instance de file. + """ + if not isinstance(fichier, file): + fichier = file(fichier) + + encoding = fichier.readline() + matched = re.search(r'^Encoding:\s*([^\r\n]*)', encoding) + if matched: + encoding = matched.group(1) + else: + raise SyntaxError("Encoding manquant dans template") + + subject = fichier.readline() + matched = re.search(r'^Subject:\s*([^\r\n]*)', subject) + if matched: + subject = matched.group(1).decode(encoding) + else: + raise SyntaxError("Subject manquant dans template") + + if fichier.readline() not in ['\r\n', '\n']: + raise SyntaxError("le fichier n'a pas le bon format") + + body = fichier.read().decode(encoding) + return subject, body