2525 examined. The text/plain subparts are assembled to form the textual
2626 body of the message, to be stored in the file associated with a "msg"
2727 class node. Any parts of other types are each stored in separate files
28- and given "file" class nodes that are linked to the "msg" node.
28+ and given "file" class nodes that are linked to the "msg" node.
2929 . In a multipart/alternative message or part, we look for a text/plain
3030 subpart and ignore the other parts.
3131
@@ -35,7 +35,7 @@ class node. Any parts of other types are each stored in separate files
3535section in the message body. The message body is divided into sections by
3636blank lines. Sections where the second and all subsequent lines begin with
3737a ">" or "|" character are considered "quoting sections". The first line of
38- the first non-quoting section becomes the summary of the message.
38+ the first non-quoting section becomes the summary of the message.
3939
4040Addresses
4141---------
@@ -48,33 +48,33 @@ class node. Any parts of other types are each stored in separate files
4848address. (The web interface does not permit logins for users with no
4949passwords.) If we prefer to reject mail from outside sources, we can simply
5050register an auditor on the "user" class that prevents the creation of user
51- nodes with no passwords.
51+ nodes with no passwords.
5252
5353Actions
5454-------
5555The subject line of the incoming message is examined to determine whether
5656the message is an attempt to create a new item or to discuss an existing
5757item. A designator enclosed in square brackets is sought as the first thing
58- on the subject line (after skipping any "Fwd:" or "Re:" prefixes).
58+ on the subject line (after skipping any "Fwd:" or "Re:" prefixes).
5959
6060If an item designator (class name and id number) is found there, the newly
6161created "msg" node is added to the "messages" property for that item, and
62- any new "file" nodes are added to the "files" property for the item.
62+ any new "file" nodes are added to the "files" property for the item.
6363
6464If just an item class name is found there, we attempt to create a new item
6565of that class with its "messages" property initialized to contain the new
6666"msg" node and its "files" property initialized to contain any new "file"
67- nodes.
67+ nodes.
6868
6969Triggers
7070--------
7171Both cases may trigger detectors (in the first case we are calling the
7272set() method to add the message to the item's spool; in the second case we
7373are calling the create() method to create a new node). If an auditor raises
7474an exception, the original message is bounced back to the sender with the
75- explanatory message given in the exception.
75+ explanatory message given in the exception.
7676
77- $Id: mailgw.py,v 1.151 2004-07-14 01:12:25 richard Exp $
77+ $Id: mailgw.py,v 1.152 2004-07-26 09:29:22 a1s Exp $
7878"""
7979__docformat__ = 'restructuredtext'
8080
@@ -211,7 +211,7 @@ def getbody(self):
211211 data = None
212212 if encoding == 'base64' :
213213 # BUG: is base64 really used for text encoding or
214- # are we inserting zip files here.
214+ # are we inserting zip files here.
215215 data = binascii .a2b_base64 (self .fp .read ())
216216 elif encoding == 'quoted-printable' :
217217 # the quopri module wants to work with files
@@ -223,7 +223,7 @@ def getbody(self):
223223 else :
224224 # take it as text
225225 data = self .fp .read ()
226-
226+
227227 # Encode message to unicode
228228 charset = rfc2822 .unaliasCharset (self .getparam ("charset" ))
229229 if charset :
@@ -234,24 +234,24 @@ def getbody(self):
234234 else :
235235 # Leave message content as is
236236 edata = data
237-
237+
238238 return edata
239239
240240 # General multipart handling:
241- # Take the first text/plain part, anything else is considered an
241+ # Take the first text/plain part, anything else is considered an
242242 # attachment.
243243 # multipart/mixed:
244244 # Multiple "unrelated" parts.
245245 # multipart/Alternative (rfc 1521):
246246 # Like multipart/mixed, except that we'd only want one of the
247247 # alternatives. Generally a top-level part from MUAs sending HTML
248248 # mail - there will be a text/plain version.
249- # multipart/signed (rfc 1847):
250- # The control information is carried in the second of the two
249+ # multipart/signed (rfc 1847):
250+ # The control information is carried in the second of the two
251251 # required body parts.
252252 # ACTION: Default, so if content is text/plain we get it.
253- # multipart/encrypted (rfc 1847):
254- # The control information is carried in the first of the two
253+ # multipart/encrypted (rfc 1847):
254+ # The control information is carried in the first of the two
255255 # required body parts.
256256 # ACTION: Not handleable as the content is encrypted.
257257 # multipart/related (rfc 1872, 2112, 2387):
@@ -261,7 +261,7 @@ def getbody(self):
261261 # ACTION: Default, if we must.
262262 # multipart/report (rfc 1892):
263263 # e.g. mail system delivery status reports.
264- # ACTION: Default. Could be ignored or used for Delivery Notification
264+ # ACTION: Default. Could be ignored or used for Delivery Notification
265265 # flagging.
266266 # multipart/form-data:
267267 # For web forms only.
@@ -271,7 +271,7 @@ def extract_content(self, parent_type=None):
271271 content_type = self .gettype ()
272272 content = None
273273 attachments = []
274-
274+
275275 if content_type == 'text/plain' :
276276 content = self .getbody ()
277277 elif content_type [:10 ] == 'multipart/' :
@@ -284,7 +284,7 @@ def extract_content(self, parent_type=None):
284284 content = new_content
285285 elif new_content :
286286 attachments .append (part .as_attachment ())
287-
287+
288288 attachments .extend (new_attach )
289289 elif (parent_type == 'multipart/signed' and
290290 content_type == 'application/pgp-signature' ):
@@ -308,7 +308,7 @@ class MailGW:
308308 (\[(?P<classname>[^\d\s]+) # [issue..
309309 (?P<nodeid>\d+)? # ..1234]
310310 \])?\s*
311- (?P<title>[^[]+)? # issue title
311+ (?P<title>[^[]+)? # issue title
312312 "? # Trailing "
313313 (\[(?P<args>.+?)\])? # [prop=value]
314314 ''' , re .IGNORECASE | re .VERBOSE )
@@ -470,7 +470,7 @@ def do_pop(self, server, user='', password='', apop=0):
470470 server .pass_ (password )
471471 numMessages = len (server .list ()[1 ])
472472 for i in range (1 , numMessages + 1 ):
473- # retr: returns
473+ # retr: returns
474474 # [ pop response e.g. '+OK 459 octets',
475475 # [ array of message lines ],
476476 # number of octets ]
@@ -582,13 +582,16 @@ def handle_message(self, message):
582582 if (message .getheader ('precedence' , '' ) == 'bulk' ):
583583 raise IgnoreBulk
584584
585+ # config is used many times in this method.
586+ # make local variable for easier access
587+ config = self .instance .config
588+
585589 # XXX Don't enable. This doesn't work yet.
586590# "[^A-z.]tracker\+(?P<classname>[^\d\s]+)(?P<nodeid>\d+)\@some.dom.ain[^A-z.]"
587591 # handle delivery to addresses like:[email protected] 588592 # use the embedded issue number as our issue
589- # if hasattr(self.instance.config, 'EMAIL_ISSUE_ADDRESS_RE') and \
590- # self.instance.config.EMAIL_ISSUE_ADDRESS_RE:
591- # issue_re = self.instance.config.EMAIL_ISSUE_ADDRESS_RE
593+ # issue_re = config['MAILGW_ISSUE_ADDRESS_RE']
594+ # if issue_re:
592595# for header in ['to', 'cc', 'bcc']:
593596# addresses = message.getheader(header, '')
594597# if addresses:
@@ -629,16 +632,15 @@ def handle_message(self, message):
629632 if otk :
630633 self .db .confirm_registration (otk .group ('otk' ))
631634 subject = 'Your registration to %s is complete' % \
632- self . instance . config . TRACKER_NAME
635+ config [ ' TRACKER_NAME' ]
633636 sendto = [from_list [0 ][1 ]]
634- self .mailer .standard_message (sendto , subject , '' )
637+ self .mailer .standard_message (sendto , subject , '' )
635638 return
636- elif hasattr (self .instance .config , 'MAIL_DEFAULT_CLASS' ) and \
637- self .instance .config .MAIL_DEFAULT_CLASS :
638- classname = self .instance .config .MAIL_DEFAULT_CLASS
639639 else :
640- # fail
641- m = None
640+ classname = config ['MAILGW_DEFAULT_CLASS' ]
641+ if not classname :
642+ # fail
643+ m = None
642644
643645 if not m :
644646 raise MailUsageError , """
@@ -724,12 +726,15 @@ def handle_message(self, message):
724726 for option , propstring in self .arguments :
725727 if option in ( '-C' , '--class' ):
726728 current_class = propstring .strip ()
729+ # XXX this is not flexible enough.
730+ # we should chect for subclasses of these classes,
731+ # not for the class name...
727732 if current_class not in ('msg' , 'file' , 'user' , 'issue' ):
728733 raise MailUsageError , '''
729734The mail gateway is not properly set up. Please contact
730735%s and have them fix the incorrect class specified as:
731736 %s
732- ''' % ( self . instance . config . ADMIN_EMAIL , current_class )
737+ ''' % ( config [ ' ADMIN_EMAIL' ] , current_class )
733738 if option in ('-S' , '--set' ):
734739 if current_class == 'issue' :
735740 errors , issue_props = setPropArrayFromString (self ,
@@ -751,7 +756,7 @@ def handle_message(self, message):
751756The mail gateway is not properly set up. Please contact
752757%s and have them fix the incorrect properties:
753758 %s
754- ''' % (self . instance . config . ADMIN_EMAIL , errors )
759+ ''' % (config [ ' ADMIN_EMAIL' ] , errors )
755760
756761 #
757762 # handle the users
@@ -803,7 +808,7 @@ def handle_message(self, message):
803808
804809 # now update the recipients list
805810 recipients = []
806- tracker_email = self . instance . config . TRACKER_EMAIL .lower ()
811+ tracker_email = config [ ' TRACKER_EMAIL' ] .lower ()
807812 for recipient in message .getaddrlist ('to' ) + message .getaddrlist ('cc' ):
808813 r = recipient [1 ].strip ().lower ()
809814 if r == tracker_email or not r :
@@ -849,7 +854,7 @@ def handle_message(self, message):
849854 # generate a messageid if there isn't one
850855 if not messageid :
851856 messageid = "<%s.%s.%s%s@%s>" % (time .time (), random .random (),
852- classname , nodeid , self . instance . config . MAIL_DOMAIN )
857+ classname , nodeid , config [ ' MAIL_DOMAIN' ] )
853858
854859 # now handle the body - find the message
855860 content , attachments = message .extract_content ()
@@ -858,19 +863,17 @@ def handle_message(self, message):
858863Roundup requires the submission to be plain text. The message parser could
859864not find a text/plain part to use.
860865'''
861-
866+
862867 # figure how much we should muck around with the email body
863- keep_citations = getattr (self .instance .config , 'EMAIL_KEEP_QUOTED_TEXT' ,
864- 'no' ) == 'yes'
865- keep_body = getattr (self .instance .config , 'EMAIL_LEAVE_BODY_UNCHANGED' ,
866- 'no' ) == 'yes'
868+ keep_citations = config ['MAILGW_KEEP_QUOTED_TEXT' ]
869+ keep_body = config ['MAILGW_LEAVE_BODY_UNCHANGED' ]
867870
868871 # parse the body of the message, stripping out bits as appropriate
869872 summary , content = parseContent (content , keep_citations ,
870873 keep_body )
871874 content = content .strip ()
872875
873- #
876+ #
874877 # handle the attachments
875878 #
876879 if properties .has_key ('files' ):
@@ -895,7 +898,7 @@ def handle_message(self, message):
895898 # pre-load the files list
896899 props ['files' ] = files
897900
898- #
901+ #
899902 # create the message if there's a message body (content)
900903 #
901904 if (content and properties .has_key ('messages' )):
@@ -942,7 +945,7 @@ def handle_message(self, message):
942945
943946 return nodeid
944947
945-
948+
946949def setPropArrayFromString (self , cl , propString , nodeid = None ):
947950 ''' takes string of form prop=value,value;prop2=value
948951 and returns (error, prop[..])
@@ -1042,13 +1045,13 @@ def uidFromAddress(db, address, create=1, **user_props):
10421045
10431046def parseContent (content , keep_citations , keep_body ,
10441047 blank_line = re .compile (r'[\r\n]+\s*[\r\n]+' ),
1045- eol = re .compile (r'[\r\n]+' ),
1048+ eol = re .compile (r'[\r\n]+' ),
10461049 signature = re .compile (r'^[>|\s]*-- ?$' ),
10471050 original_msg = re .compile (r'^[>|\s]*-----\s?Original Message\s?-----$' )):
10481051 ''' The message body is divided into sections by blank lines.
10491052 Sections where the second and all subsequent lines begin with a ">"
10501053 or "|" character are considered "quoting sections". The first line of
1051- the first non-quoting section becomes the summary of the message.
1054+ the first non-quoting section becomes the summary of the message.
10521055
10531056 If keep_citations is true, then we keep the "quoting sections" in the
10541057 content.
@@ -1122,4 +1125,4 @@ def parseContent(content, keep_citations, keep_body,
11221125
11231126 return summary , content
11241127
1125- # vim: set filetype=python sts=4 sw=4 et si
1128+ # vim: set filetype=python sts=4 sw=4 et si :
0 commit comments