Parent: [e416fe] (diff)

Child: [ccd95e] (diff)

Download this file

mail_tasks.py    145 lines (136 with data), 5.8 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import logging
from pylons import c, g
from bson import ObjectId
from allura.lib import helpers as h
from allura.lib.decorators import task
from allura.lib import mail_util
from allura.lib import exceptions as exc
log = logging.getLogger(__name__)
smtp_client = mail_util.SMTPClient()
@task
def route_email(
peer, mailfrom, rcpttos, data):
'''Route messages according to their destination:
<topic>@<mount_point>.<subproj2>.<subproj1>.<project>.projects.sourceforge.net
gets sent to c.app.handle_message(topic, message)
'''
try:
msg = mail_util.parse_message(data)
except: # pragma no cover
log.exception('Parse Error: (%r,%r,%r)', peer, mailfrom, rcpttos)
return
mail_user = mail_util.identify_sender(peer, mailfrom, msg['headers'], msg)
with h.push_config(c, user=mail_user):
log.info('Received email from %s', c.user.username)
# For each of the addrs, determine the project/app and route appropriately
for addr in rcpttos:
try:
userpart, project, app = mail_util.parse_address(addr)
with h.push_config(c, project=project, app=app):
if not app.has_access(c.user, userpart):
log.info('Access denied for %s to mailbox %s', c.user, userpart)
else:
if msg['multipart']:
msg_hdrs = msg['headers']
for part in msg['parts']:
if part.get('content_type', '').startswith('multipart/'): continue
msg = dict(
headers=dict(msg_hdrs, **part['headers']),
message_id=part['message_id'],
in_reply_to=part['in_reply_to'],
references=part['references'],
filename=part['filename'],
content_type=part['content_type'],
payload=part['payload'])
c.app.handle_message(userpart, msg)
else:
c.app.handle_message(userpart, msg)
except exc.MailError, e:
log.error('Error routing email to %s: %s', addr, e)
except:
log.exception('Error routing mail to %s', addr)
@task
def sendmail(fromaddr, destinations, text, reply_to, subject,
message_id, in_reply_to=None):
from allura import model as M
addrs_plain = []
addrs_html = []
addrs_multi = []
if fromaddr is None:
fromaddr = u'noreply@in.sf.net'
elif '@' not in fromaddr:
log.warning('Looking up user with fromaddr %s', fromaddr)
user = M.User.query.get(_id=ObjectId(fromaddr))
if not user:
log.warning('Cannot find user with ID %s', fromaddr)
fromaddr = u'noreply@in.sf.net'
else:
fromaddr = user.email_address_header()
# Divide addresses based on preferred email formats
for addr in destinations:
if mail_util.isvalid(addr):
addrs_plain.append(addr)
else:
try:
user = M.User.query.get(_id=ObjectId(addr))
if not user:
log.warning('Cannot find user with ID %s', addr)
continue
except:
log.exception('Error looking up user with ID %r' % addr)
continue
addr = user.email_address_header()
if not addr and user.email_addresses:
addr = user.email_addresses[0]
log.warning('User %s has not set primary email address, using %s',
user._id, addr)
if not addr:
log.error("User %s (%s) has not set any email address, can't deliver",
user._id, user.username)
continue
if user.get_pref('email_format') == 'plain':
addrs_plain.append(addr)
elif user.get_pref('email_format') == 'html':
addrs_html.append(addr)
else:
addrs_multi.append(addr)
plain_msg = mail_util.encode_email_part(text, 'plain')
html_text = g.forge_markdown(email=True).convert(text)
html_msg = mail_util.encode_email_part(html_text, 'html')
multi_msg = mail_util.make_multipart_message(plain_msg, html_msg)
smtp_client.sendmail(
addrs_multi, fromaddr, reply_to, subject, message_id,
in_reply_to, multi_msg)
smtp_client.sendmail(
addrs_plain, fromaddr, reply_to, subject, message_id,
in_reply_to, plain_msg)
smtp_client.sendmail(
addrs_html, fromaddr, reply_to, subject, message_id,
in_reply_to, html_msg)
@task
def sendsimplemail(
fromaddr,
toaddr,
text,
reply_to,
subject,
message_id,
in_reply_to=None):
from allura import model as M
if fromaddr is None:
fromaddr = u'noreply@in.sf.net'
elif '@' not in fromaddr:
log.warning('Looking up user with fromaddr %s', fromaddr)
user = M.User.query.get(_id=ObjectId(fromaddr))
if not user:
log.warning('Cannot find user with ID %s', fromaddr)
fromaddr = u'noreply@in.sf.net'
else:
fromaddr = user.email_address_header()
plain_msg = mail_util.encode_email_part(text, 'plain')
html_text = g.forge_markdown(email=True).convert(text)
html_msg = mail_util.encode_email_part(html_text, 'html')
multi_msg = mail_util.make_multipart_message(plain_msg, html_msg)
smtp_client.sendmail(
[toaddr], fromaddr, reply_to, subject, message_id,
in_reply_to, multi_msg)