source: mailtotracplugin/0.12/plugin/mail2trac/utils.py

Last change on this file was 16530, checked in by Ryan J Ollos, 6 years ago

Fix indentation

File size: 5.0 KB
Line 
1"""utility functions for mail2trac"""
2
3import base64
4import email
5import email.Utils
6import re
7import os
8import smtplib
9from trac.attachment import Attachment
10from StringIO import StringIO
11from email.header import decode_header
12
13
14
15
16### Trac-specific functions
17
18def emailaddr2user(env, addr):
19    """returns Trac user name from an email address"""
20    cnx = env.get_read_db()
21    name, address = email.Utils.parseaddr(addr)
22    toto = env.get_known_users()
23    for user in env.get_known_users():
24        if address == user[2]: # get_known_users return (username, name, email), we want the mail
25            return user[0]
26
27
28def send_email(env, from_addr, recipients, message):
29    """
30    BBB method for sending mail;  trunk already has a nice API;
31    see http://trac.edgewall.org/browser/trunk/trac/notification.py
32    """
33
34    # options from trac.ini
35    smtp_server = env.config.get('notification', 'smtp_server')
36    smtp_port = int(env.config.get('notification', 'smtp_port') or 25)
37    smtp_user = env.config.get('notification', 'smtp_user')
38    smtp_password = env.config.get('notification', 'smtp_password')
39
40    print "smtp_server : %s\n, smtp_port :%s\ni, smtp_user :%s\n,  smtp_password :%s\n"%(smtp_server, smtp_port, smtp_user, smtp_password)
41
42
43    # ensure list of recipients
44    if isinstance(recipients, basestring):
45        recipients = [ recipients ]
46
47    # send the email
48    session = smtplib.SMTP(smtp_server, smtp_port)
49    if smtp_user: # authenticate
50        session.login(smtp_user.encode('utf-8'),
51                      smtp_password.encode('utf-8'))
52    session.sendmail(from_addr, recipients, message)
53
54def add_attachments(env, ticket, attachments):
55    """add attachments to the ticket"""
56    ctr = 1
57    if not attachments : return
58    for msg in attachments:
59        attachment = Attachment(env, 'ticket', ticket.id)
60        attachment.author = ticket['reporter']
61        #attachment.description = ticket['summary']
62        payload = msg.get_payload()
63        if msg.get('Content-Transfer-Encoding') == 'base64':
64            payload = base64.b64decode(payload)
65        size = len(payload)
66        filename = msg.get_filename() or message.get('Subject')
67        if not filename:
68            filename = 'attachment-%d' % ctr
69            extensions = KNOWN_MIME_TYPES.get(message.get_content_type())
70            if extensions:
71                filename += '.%s' % extensions[0]
72            ctr += 1
73        buffer = StringIO()
74        print >> buffer, payload
75        buffer.seek(0)
76        attachment.insert(filename, buffer, size)
77        os.chmod(attachment.path, 0666)
78        # TODO : should probably chown too
79
80### generic email functions
81
82
83def get_decoded_subject(message) :
84    #decode subject
85    decoded_subject = u''
86    for x in decode_header(message['subject']) :
87        if x[1] : #specific encoding
88            decoded_subject += unicode(x[0], x[1]) + u' '
89        else :
90            decoded_subject += x[0] + u' '
91    decoded_subject = decoded_subject.strip()
92    return decoded_subject
93
94
95def reply_subject(subject):
96    """subject line appropriate to reply"""
97    subject = subject.strip()
98    return 'Re: %s' % subject
99
100def reply_body(body, message):
101    """
102    body appropriate to a reply message
103    """
104    payload = message.get_payload(decode = True)
105    if isinstance(payload, basestring):
106        body += '\n\nOriginal message:\n %s' % payload
107    return body
108
109def get_body_and_attachments(message, description=None, attachments=[]):
110    contents = {}
111    attachments = []
112    for part in message.walk():
113        if part.get_content_maintype() == 'multipart':
114            continue
115
116        ctype        = part.get_content_type()
117        ctype = ctype.split(';')[0]
118        cdisposition = part.get('content-disposition')
119        cdisposition = (cdisposition or '').split(';')[0].strip()
120
121
122        if cdisposition != 'attachment':
123
124            if ctype not in ('text/plain', 'text/html'):
125                continue
126
127            if not contents.has_key(ctype):
128                payload = part.get_payload(decode = True)
129                charset = part.get_charsets('ascii')[0]
130
131                try:
132                    payload = unicode(payload, charset, 'replace')
133                except LookupError:
134                    payload = unicode(payload, 'ISO-8859-1', 'replace')
135
136                contents[ctype] = payload
137            continue
138        elif (ctype not in ('application/pgp-signature')) :
139            file_name = part.get_filename()
140            attachments.append(part)
141    return contents['text/plain'], attachments
142
143
144subject_re = re.compile('( *[Rr][Ee] *:? *)*(.*)')
145
146def strip_res(subject):
147    """strip the REs from a Subject line"""
148    match = subject_re.match(subject)
149    return match.groups()[-1]
150
151def strip_quotes(message):
152    """strip quotes from a message string"""
153    body = []
154    on_regex = re.compile('On .*, .* wrote:')
155    for line in message.splitlines():
156        line = line.strip()
157        if line.strip().startswith('>'):
158            continue
159        if on_regex.match(line):
160            continue
161        body.append(line)
162    body = '\n'.join(body)
163    return body.strip()
Note: See TracBrowser for help on using the repository browser.