##// END OF EJS Templates
emails: make bad headers error show what headers we investigated....
marcink -
r1727:25849370 default
parent child Browse files
Show More
@@ -1,183 +1,188 b''
1 from rhodecode.lib.rcmail.response import MailResponse
1 from rhodecode.lib.rcmail.response import MailResponse
2
2
3 from rhodecode.lib.rcmail.exceptions import BadHeaders
3 from rhodecode.lib.rcmail.exceptions import BadHeaders
4 from rhodecode.lib.rcmail.exceptions import InvalidMessage
4 from rhodecode.lib.rcmail.exceptions import InvalidMessage
5
5
6
6
7 class Attachment(object):
7 class Attachment(object):
8 """
8 """
9 Encapsulates file attachment information.
9 Encapsulates file attachment information.
10
10
11 :param filename: filename of attachment
11 :param filename: filename of attachment
12 :param content_type: file mimetype
12 :param content_type: file mimetype
13 :param data: the raw file data, either as string or file obj
13 :param data: the raw file data, either as string or file obj
14 :param disposition: content-disposition (if any)
14 :param disposition: content-disposition (if any)
15 """
15 """
16
16
17 def __init__(self,
17 def __init__(self,
18 filename=None,
18 filename=None,
19 content_type=None,
19 content_type=None,
20 data=None,
20 data=None,
21 disposition=None):
21 disposition=None):
22
22
23 self.filename = filename
23 self.filename = filename
24 self.content_type = content_type
24 self.content_type = content_type
25 self.disposition = disposition or 'attachment'
25 self.disposition = disposition or 'attachment'
26 self._data = data
26 self._data = data
27
27
28 @property
28 @property
29 def data(self):
29 def data(self):
30 if isinstance(self._data, basestring):
30 if isinstance(self._data, basestring):
31 return self._data
31 return self._data
32 self._data = self._data.read()
32 self._data = self._data.read()
33 return self._data
33 return self._data
34
34
35
35
36 class Message(object):
36 class Message(object):
37 """
37 """
38 Encapsulates an email message.
38 Encapsulates an email message.
39
39
40 :param subject: email subject header
40 :param subject: email subject header
41 :param recipients: list of email addresses
41 :param recipients: list of email addresses
42 :param body: plain text message
42 :param body: plain text message
43 :param html: HTML message
43 :param html: HTML message
44 :param sender: email sender address
44 :param sender: email sender address
45 :param cc: CC list
45 :param cc: CC list
46 :param bcc: BCC list
46 :param bcc: BCC list
47 :param extra_headers: dict of extra email headers
47 :param extra_headers: dict of extra email headers
48 :param attachments: list of Attachment instances
48 :param attachments: list of Attachment instances
49 :param recipients_separator: alternative separator for any of
49 :param recipients_separator: alternative separator for any of
50 'From', 'To', 'Delivered-To', 'Cc', 'Bcc' fields
50 'From', 'To', 'Delivered-To', 'Cc', 'Bcc' fields
51 """
51 """
52
52
53 def __init__(self,
53 def __init__(self,
54 subject=None,
54 subject=None,
55 recipients=None,
55 recipients=None,
56 body=None,
56 body=None,
57 html=None,
57 html=None,
58 sender=None,
58 sender=None,
59 cc=None,
59 cc=None,
60 bcc=None,
60 bcc=None,
61 extra_headers=None,
61 extra_headers=None,
62 attachments=None,
62 attachments=None,
63 recipients_separator="; "):
63 recipients_separator="; "):
64
64
65 self.subject = subject or ''
65 self.subject = subject or ''
66 self.sender = sender
66 self.sender = sender
67 self.body = body
67 self.body = body
68 self.html = html
68 self.html = html
69
69
70 self.recipients = recipients or []
70 self.recipients = recipients or []
71 self.attachments = attachments or []
71 self.attachments = attachments or []
72 self.cc = cc or []
72 self.cc = cc or []
73 self.bcc = bcc or []
73 self.bcc = bcc or []
74 self.extra_headers = extra_headers or {}
74 self.extra_headers = extra_headers or {}
75
75
76 self.recipients_separator = recipients_separator
76 self.recipients_separator = recipients_separator
77
77
78 @property
78 @property
79 def send_to(self):
79 def send_to(self):
80 return set(self.recipients) | set(self.bcc or ()) | set(self.cc or ())
80 return set(self.recipients) | set(self.bcc or ()) | set(self.cc or ())
81
81
82 def to_message(self):
82 def to_message(self):
83 """
83 """
84 Returns raw email.Message instance.Validates message first.
84 Returns raw email.Message instance.Validates message first.
85 """
85 """
86
86
87 self.validate()
87 self.validate()
88
88
89 return self.get_response().to_message()
89 return self.get_response().to_message()
90
90
91 def get_response(self):
91 def get_response(self):
92 """
92 """
93 Creates a Lamson MailResponse instance
93 Creates a Lamson MailResponse instance
94 """
94 """
95
95
96 response = MailResponse(Subject=self.subject,
96 response = MailResponse(Subject=self.subject,
97 To=self.recipients,
97 To=self.recipients,
98 From=self.sender,
98 From=self.sender,
99 Body=self.body,
99 Body=self.body,
100 Html=self.html,
100 Html=self.html,
101 separator=self.recipients_separator)
101 separator=self.recipients_separator)
102
102
103 if self.cc:
103 if self.cc:
104 response.base['Cc'] = self.cc
104 response.base['Cc'] = self.cc
105
105
106 for attachment in self.attachments:
106 for attachment in self.attachments:
107
107
108 response.attach(attachment.filename,
108 response.attach(attachment.filename,
109 attachment.content_type,
109 attachment.content_type,
110 attachment.data,
110 attachment.data,
111 attachment.disposition)
111 attachment.disposition)
112
112
113 response.update(self.extra_headers)
113 response.update(self.extra_headers)
114
114
115 return response
115 return response
116
116
117 def _get_headers(self):
118 headers = [self.subject, self.sender]
119 headers += list(self.send_to)
120 headers += self.extra_headers.values()
121 return headers
122
117 def is_bad_headers(self):
123 def is_bad_headers(self):
118 """
124 """
119 Checks for bad headers i.e. newlines in subject, sender or recipients.
125 Checks for bad headers i.e. newlines in subject, sender or recipients.
120 """
126 """
121
127
122 headers = [self.subject, self.sender]
128 headers = self._get_headers()
123 headers += list(self.send_to)
124 headers += self.extra_headers.values()
125
129
126 for val in headers:
130 for val in headers:
127 for c in '\r\n':
131 for c in '\r\n':
128 if c in val:
132 if c in val:
129 return True
133 return True
130 return False
134 return False
131
135
132 def validate(self):
136 def validate(self):
133 """
137 """
134 Checks if message is valid and raises appropriate exception.
138 Checks if message is valid and raises appropriate exception.
135 """
139 """
136
140
137 if not self.recipients:
141 if not self.recipients:
138 raise InvalidMessage("No recipients have been added")
142 raise InvalidMessage("No recipients have been added")
139
143
140 if not self.body and not self.html:
144 if not self.body and not self.html:
141 raise InvalidMessage("No body has been set")
145 raise InvalidMessage("No body has been set")
142
146
143 if not self.sender:
147 if not self.sender:
144 raise InvalidMessage("No sender address has been set")
148 raise InvalidMessage("No sender address has been set")
145
149
146 if self.is_bad_headers():
150 if self.is_bad_headers():
147 raise BadHeaders
151 headers = self._get_headers()
152 raise BadHeaders(headers)
148
153
149 def add_recipient(self, recipient):
154 def add_recipient(self, recipient):
150 """
155 """
151 Adds another recipient to the message.
156 Adds another recipient to the message.
152
157
153 :param recipient: email address of recipient.
158 :param recipient: email address of recipient.
154 """
159 """
155
160
156 self.recipients.append(recipient)
161 self.recipients.append(recipient)
157
162
158 def add_cc(self, recipient):
163 def add_cc(self, recipient):
159 """
164 """
160 Adds an email address to the CC list.
165 Adds an email address to the CC list.
161
166
162 :param recipient: email address of recipient.
167 :param recipient: email address of recipient.
163 """
168 """
164
169
165 self.cc.append(recipient)
170 self.cc.append(recipient)
166
171
167 def add_bcc(self, recipient):
172 def add_bcc(self, recipient):
168 """
173 """
169 Adds an email address to the BCC list.
174 Adds an email address to the BCC list.
170
175
171 :param recipient: email address of recipient.
176 :param recipient: email address of recipient.
172 """
177 """
173
178
174 self.bcc.append(recipient)
179 self.bcc.append(recipient)
175
180
176 def attach(self, attachment):
181 def attach(self, attachment):
177 """
182 """
178 Adds an attachment to the message.
183 Adds an attachment to the message.
179
184
180 :param attachment: an **Attachment** instance.
185 :param attachment: an **Attachment** instance.
181 """
186 """
182
187
183 self.attachments.append(attachment)
188 self.attachments.append(attachment)
General Comments 0
You need to be logged in to leave comments. Login now