def send_mail(from_addr, to_addr, subject, content, attachment=None, output_encode="utf-8"): mail = MIMEMultipart() mail["From"] = from_addr mail["To"] = ";".join(to_addr) mail["Subject"] = Header(subject, output_encode) text = MIMEText(content, "plain", output_encode) mail.attach(text) att_names = [] for name, attach in attachment: att_names.append(name) att = MIMEBase("application", "octet-stream") att.set_payload(attach, output_encode) name_encoded = base64mime.header_encode(name, output_encode) att.add_header("content-disposition", "attachment", filename="%s" % name_encoded) mail.attach(att) print "Sending %s to %s..." % (subject, to_addr), try: server = smtplib.SMTP("localhost") server.sendmail(from_addr, to_addr, mail.as_string()) server.quit() print "Done." print "Attachment list:\n %s" % "\n ".join(att_names) return True except Exception, e: print "Failed.\n %s" % e return False
def _encodeEmail(self, name, e): if name and not self._isAscii(name): return utils.formataddr((base64mime.header_encode(name, 'utf-8'), e)) return utils.formataddr((name, e))
def _start_transaction(self, conn, req): """ The real workhorse. """ self._update_socket_timeout(conn, req) conn.putrequest(req.get_method(), req.get_selector(), skip_host=1, skip_accept_encoding=1) # We're always sending HTTP/1.1, which makes connection keep alive a # default, BUT since the browsers (Chrome at least) send this header # in their HTTP/1.1 requests we're going to do the same just to make # sure we behave like a browser if not req.has_header('Connection'): conn.putheader('Connection', 'keep-alive') data = req.get_data() if data is not None: data = str(data) if not req.has_header('Content-type'): conn.putheader('Content-type', DEFAULT_CONTENT_TYPE) if not req.has_header('Content-length'): conn.putheader('Content-length', '%d' % len(data)) # Add headers header_dict = dict(self.parent.addheaders) header_dict.update(req.headers) header_dict.update(req.unredirected_hdrs) for k, v in header_dict.iteritems(): # # Handle case where the key or value is None (strange but could happen) # if k is None: continue if v is None: v = '' # # Encode the key and value as UTF-8 and try to send them to the wire # k = to_utf8_raw(k) v = to_utf8_raw(v) try: conn.putheader(k, v) except ValueError: # # The httplib adds some restrictions to the characters which can # be sent in header names and values (see putheader function # definition). # # Sending non-ascii characters in HTTP header values is difficult, # since servers usually ignore the encoding. From stackoverflow: # # Historically, HTTP has allowed field content with text in the # ISO-8859-1 charset [ISO-8859-1], supporting other charsets only # through use of [RFC2047] encoding. In practice, most HTTP header # field values use only a subset of the US-ASCII charset [USASCII]. # Newly defined header fields SHOULD limit their field values to # US-ASCII octets. A recipient SHOULD treat other octets in field # content (obs-text) as opaque data. # # TL;DR: we use RFC2047 encoding here, knowing that it will only # work in 1% of the remote servers, but it is our best bet # if not _is_legal_header_name(k): k = header_encode(k, charset='utf-8', keep_eols=True) if _is_illegal_header_value(v): v = header_encode(v, charset='utf-8', keep_eols=True) conn.putheader(k, v) conn.endheaders() if data is not None: conn.send(data)