[IMP] email_template add email_send method and create email.message record and also...
authorYSA (Openerp) <ysa@tinyerp.com>
Wed, 2 Feb 2011 13:13:23 +0000 (18:43 +0530)
committerYSA (Openerp) <ysa@tinyerp.com>
Wed, 2 Feb 2011 13:13:23 +0000 (18:43 +0530)
bzr revid: ysa@tinyerp.com-20110202131323-lz1g0rx1b0ibabmw

addons/email/email_message.py
addons/email/email_message_view.xml
addons/email/email_smtp_server.py

index a5a890d..a8d0957 100644 (file)
@@ -132,9 +132,7 @@ class email_message(osv.osv):
         'name':fields.text('Subject', readonly=True),
         'model': fields.char('Object Name', size=128, select=1, readonly=True),
         'res_id': fields.integer('Resource ID', select=1, readonly=True),
-        'ref_id': fields.char('Reference Id', size=256, readonly=True, help="Message Id in Email Server.", select=True),
         'date': fields.datetime('Date', readonly=True),
-        'history': fields.boolean('Is History?', readonly=True),
         'user_id': fields.many2one('res.users', 'User Responsible', readonly=True),
         'message': fields.text('Description', readonly=True),
         'email_from': fields.char('From', size=128, help="Email From", readonly=True),
@@ -143,12 +141,14 @@ class email_message(osv.osv):
         'email_bcc': fields.char('Bcc', help='Blind Carbon Copy Email Recipients', size=256, readonly=True),
         'message_id': fields.char('Message Id', size=1024, readonly=True, help="Message Id on Email.", select=True),
         'references': fields.text('References', readonly=True, help="References emails."),
-        'description': fields.text('Description', readonly=True),
         'partner_id': fields.many2one('res.partner', 'Partner', required=False),
         'attachment_ids': fields.many2many('ir.attachment', 'message_attachment_rel', 'message_id', 'attachment_id', 'Attachments', readonly=True),
         'display_text': fields.function(_get_display_text, method=True, type='text', size="512", string='Display Text'),
         'reply_to':fields.char('Reply-To', size=250, readonly=True),
-        'account_id' :fields.many2one('email.smtp_server', 'User account', required=True, readonly=True),
+        'account_id' :fields.many2one('email.smtp_server', 'User account', readonly=True),
+        'sub_type': fields.char('Sub Type', size=32, readonly=True),
+        'x_headers': fields.char('x_headers',size=256, readonly=True),
+        'priority':fields.integer('Priority', readonly=True),
         #I like GMAIL which allows putting same mail in many folders
         #Lets plan it for 0.9
         'folder':fields.selection([
@@ -160,7 +160,7 @@ class email_message(osv.osv):
         'state':fields.selection([
                         ('na', 'Not Applicable'),
                         ('sending', 'Sending'),
-                        ('wait', 'Waiting'),
+                        ('waiting', 'Waiting'),
                         ], 'Status', required=True, readonly=True),
     }
 
index 1478fe4..43bde18 100644 (file)
                                     <button name="open_document" string="Open Document" type="object" icon="gtk-jump-to"/>
                                 </group>
                                 <field name="message_id"/>
-                                <field name="ref_id"/>
                            </group>
-                           <separator string="Description" colspan="4"/>
-                            <field name="description" nolabel="1" colspan="4" />
                         </page>
                         <page string="Attachments">
                             <separator string="Attachments" colspan="4"/>
@@ -48,6 +45,9 @@
                             <field name="account_id" colspan="2" />
                             <field name="folder" colspan="2" select="2"/>
                             <field name="state"/>
+                            <field name="sub_type"/>
+                            <field name="x_headers"/>
+                            <field name="priority"/>
                         </page>
                     </notebook>
                 </form>
index bcbeede..9bbafc0 100644 (file)
 #
 ##############################################################################
 
-from osv import osv, fields
-import re
-import smtplib
-import base64
-from email import Encoders
-from email.mime.base import MIMEBase
-from email.mime.multipart import MIMEMultipart
-from email.mime.text import MIMEText
-from email.header import decode_header, Header
-from email.utils import formatdate
-import netsvc
-import datetime
+from osv import osv
+from osv import fields
 from tools.translate import _
-import tools
-import logging
+import time
 
-EMAIL_PATTERN = re.compile(r'([^()\[\] ,<:\\>@";]+@[^()\[\] ,<:\\>@";]+)') # See RFC822
-def extract_emails(emails_str):
-    """
-    Returns a list of email addresses recognized in a string, ignoring the rest of the string.
-    extract_emails('a@b.com,c@bcom, "John Doe" <d@b.com> , e@b.com') -> ['a@b.com','c@bcom', 'd@b.com', 'e@b.com']"
-    """
-    return EMAIL_PATTERN.findall(emails_str)
-
-
-def extract_emails_from_dict(addresses={}):
-    """
-    Extracts email addresses from a dictionary with comma-separated address string values, handling
-    separately the To, CC, BCC and Reply-To addresses.
+#import re
+#import smtplib
+#import base64
+#from email import Encoders
+#from email.mime.base import MIMEBase
+#from email.mime.multipart import MIMEMultipart
+#from email.mime.text import MIMEText
+#from email.header import decode_header, Header
+#from email.utils import formatdate
+#import netsvc
+#import datetime
+#import tools
+#import logging
 
-    :param addresses: a dictionary of addresses in the form {'To': 'a@b.com,c@bcom; d@b.com;e@b.com' , 'CC': 'e@b.com;f@b.com', ... }
-    :return: a dictionary with a list of separate addresses for each header (To, CC, BCC), with an additional key 'all-recipients'
-             containing all addresses for the 'To', 'CC', 'BCC' entries.
-    """
-    result = {'all-recipients':[]}
-    keys = ['To', 'CC', 'BCC', 'Reply-To']
-    for each in keys:
-        emails = extract_emails(addresses.get(each, u''))
-        while u'' in emails:
-            emails.remove(u'')
-        result[each] = emails
-        if each != 'Reply-To':
-            result['all-recipients'].extend(emails)
-    return result
+#EMAIL_PATTERN = re.compile(r'([^()\[\] ,<:\\>@";]+@[^()\[\] ,<:\\>@";]+)') # See RFC822
+#def extract_emails(emails_str):
+#    """
+#    Returns a list of email addresses recognized in a string, ignoring the rest of the string.
+#    extract_emails('a@b.com,c@bcom, "John Doe" <d@b.com> , e@b.com') -> ['a@b.com','c@bcom', 'd@b.com', 'e@b.com']"
+#    """
+#    return EMAIL_PATTERN.findall(emails_str)
+#
+#
+#def extract_emails_from_dict(addresses={}):
+#    """
+#    Extracts email addresses from a dictionary with comma-separated address string values, handling
+#    separately the To, CC, BCC and Reply-To addresses.
+#
+#    :param addresses: a dictionary of addresses in the form {'To': 'a@b.com,c@bcom; d@b.com;e@b.com' , 'CC': 'e@b.com;f@b.com', ... }
+#    :return: a dictionary with a list of separate addresses for each header (To, CC, BCC), with an additional key 'all-recipients'
+#             containing all addresses for the 'To', 'CC', 'BCC' entries.
+#    """
+#    result = {'all-recipients':[]}
+#    keys = ['To', 'CC', 'BCC', 'Reply-To']
+#    for each in keys:
+#        emails = extract_emails(addresses.get(each, u''))
+#        while u'' in emails:
+#            emails.remove(u'')
+#        result[each] = emails
+#        if each != 'Reply-To':
+#            result['all-recipients'].extend(emails)
+#    return result
 
 class email_smtp_server(osv.osv):
     """
@@ -119,15 +122,8 @@ unless it is already specified in the From Email, e.g: John Doe <john@doe.com>",
     }
 
     _defaults = {
-         'name':lambda self, cursor, user, context:self.pool.get(
-                                                'res.users'
-                                                ).read(
-                                                        cursor,
-                                                        user,
-                                                        user,
-                                                        ['name'],
-                                                        context
-                                                        )['name'],
+         'name':lambda self, cursor, user, context:self.pool.get( 'res.users'
+                                                ).read(cursor, user, user, ['name'], context)['name'],
          'state':lambda * a:'draft',
          'smtpport':lambda *a:25,
          'smtpserver':lambda *a:'localhost',
@@ -160,269 +156,311 @@ unless it is already specified in the From Email, e.g: John Doe <john@doe.com>",
     def name_get(self, cr, uid, ids, context=None):
         return [(a["id"], "%s (%s)" % (a['email_id'], a['name'])) for a in self.read(cr, uid, ids, ['name', 'email_id'], context=context)]
 
-    def get_outgoing_server(self, cursor, user, ids, context=None):
-        """
-        Returns the Out Going Connection (SMTP) object
-
-        @attention: DO NOT USE except_osv IN THIS METHOD
-        @param cursor: Database Cursor
-        @param user: ID of current user
-        @param ids: ID/list of ids of current object for
-                    which connection is required
-                    First ID will be chosen from lists
-        @param context: Context
-
-        @return: SMTP server object or Exception
-        """
-        #Type cast ids to integer
-        if type(ids) == list:
-            ids = ids[0]
-        this_object = self.browse(cursor, user, ids, context=context)
-        if this_object:
-            if this_object.smtpserver and this_object.smtpport:
-                try:
-                    if this_object.smtpssl:
-                        serv = smtplib.SMTP_SSL(this_object.smtpserver, this_object.smtpport)
-                    else:
-                        serv = smtplib.SMTP(this_object.smtpserver, this_object.smtpport)
-                    if this_object.smtptls:
-                        serv.ehlo()
-                        serv.starttls()
-                        serv.ehlo()
-                except Exception, error:
-                    raise error
-                try:
-                    if serv.has_extn('AUTH') or this_object.smtpuname or this_object.smtppass:
-                        serv.login(str(this_object.smtpuname), str(this_object.smtppass))
-                except Exception, error:
-                    raise error
-                return serv
-            raise Exception(_("SMTP SERVER or PORT not specified"))
-        raise Exception(_("Core connection for the given ID does not exist"))
-
-    def check_outgoing_connection(self, cursor, user, ids, context=None):
-        """
-        checks SMTP credentials and confirms if outgoing connection works
-        (Attached to button)
-        @param cursor: Database Cursor
-        @param user: ID of current user
-        @param ids: list of ids of current object for
-                    which connection is required
-        @param context: Context
-        """
-        try:
-            self.get_outgoing_server(cursor, user, ids, context)
-            raise osv.except_osv(_("SMTP Test Connection Was Successful"), '')
-        except osv.except_osv, success_message:
-            raise success_message
-        except Exception, error:
-            raise osv.except_osv(
-                                 _("Out going connection test failed"),
-                                 _("Reason: %s") % error
-                                 )
-
-    def do_approval(self, cr, uid, ids, context=None):
-        #TODO: Check if user has rights
-        self.write(cr, uid, ids, {'state':'approved'}, context=context)
-#        wf_service = netsvc.LocalService("workflow")
-
-    def smtp_connection(self, cursor, user, id, context=None):
-        """
-        This method should now wrap smtp_connection
-        """
-        #This function returns a SMTP server object
-        logger = netsvc.Logger()
-        core_obj = self.browse(cursor, user, id, context=context)
-        if core_obj.smtpserver and core_obj.smtpport and core_obj.state == 'approved':
-            try:
-                serv = self.get_outgoing_server(cursor, user, id, context)
-            except Exception, error:
-                logger.notifyChannel(_("Email Template"), netsvc.LOG_ERROR, _("Mail from Account %s failed on login. Probable Reason:Could not login to server\nError: %s") % (id, error))
-                return False
-            #Everything is complete, now return the connection
-            return serv
-        else:
-            logger.notifyChannel(_("Email Template"), netsvc.LOG_ERROR, _("Mail from Account %s failed. Probable Reason:Account not approved") % id)
-            return False
-
-#**************************** MAIL SENDING FEATURES ***********************#
-    def send_email(self, cr, uid, ids, addresses, subject='', body=None, payload=None, message_id=None, context=None):
-        #TODO: Replace all this with a single email object
-        if body is None:
-            body = {}
-        if payload is None:
-            payload = {}
-        if context is None:
-            context = {}
-        logger = netsvc.Logger()
-        for id in ids:
-            core_obj = self.browse(cr, uid, id, context)
-            serv = self.smtp_connection(cr, uid, id)
-            if serv:
-                try:
-                    # Need a multipart/mixed wrapper for attachments if content is alternative
-                    if payload:
-                        payload_part = MIMEMultipart(_subtype='mixed')
-                        text_part = MIMEMultipart(_subtype='mixed')
-                        payload_part.attach(text_part)
-                    else:
-                        # otherwise a single multipart/mixed will do the whole job
-                        payload_part = text_part = MIMEMultipart(_subtype='mixed')
-
-                    if subject:
-                        payload_part['Subject'] = subject
-                    from_email = core_obj.email_id
-                    if '<' in from_email:
-                        # We have a structured email address, keep it untouched
-                        payload_part['From'] = Header(core_obj.email_id, 'utf-8').encode()
-                    else:
-                        # Plain email address, construct a structured one based on the name:
-                        sender_name = Header(core_obj.name, 'utf-8').encode()
-                        payload_part['From'] = sender_name + " <" + core_obj.email_id + ">"
-                    payload_part['Organization'] = tools.ustr(core_obj.user.company_id.name)
-                    payload_part['Date'] = formatdate()
-                    addresses_l = extract_emails_from_dict(addresses)
-                    if addresses_l['To']:
-                        payload_part['To'] = u','.join(addresses_l['To'])
-                    if addresses_l['CC']:
-                        payload_part['CC'] = u','.join(addresses_l['CC'])
-                    if addresses_l['Reply-To']:
-                        payload_part['Reply-To'] = addresses_l['Reply-To'][0]
-                    if message_id:
-                        payload_part['Message-ID'] = message_id
-                    if body.get('text', False):
-                        temp_body_text = body.get('text', '')
-                        l = len(temp_body_text.replace(' ', '').replace('\r', '').replace('\n', ''))
-                        if l == 0:
-                            body['text'] = u'No Mail Message'
-                    # Attach parts into message container.
-                    # According to RFC 2046, the last part of a multipart message, in this case
-                    # the HTML message, is best and preferred.
-#                    if core_obj.send_pref in ('text', 'mixed', 'alternative'):
-#                        body_text = body.get('text', u'<Empty Message>')
-#                        body_text = tools.ustr(body_text)
-#                        text_part.attach(MIMEText(body_text.encode("utf-8"), _charset='UTF-8'))
-#                    if core_obj.send_pref in ('html', 'mixed', 'alternative'):
-                    html_body = body.get('html', u'')
-                    if len(html_body) == 0 or html_body == u'':
-                        html_body = body.get('text', u'<p>&lt;Empty Message&gt;</p>').replace('\n', '<br/>').replace('\r', '<br/>')
-                    html_body = tools.ustr(html_body)
-                    text_part.attach(MIMEText(html_body.encode("utf-8"), _subtype='html', _charset='UTF-8'))
-
-                    #Now add attachments if any, wrapping into a container multipart/mixed if needed
-                    if payload:
-                        for file in payload:
-                            part = MIMEBase('application', "octet-stream")
-                            part.set_payload(base64.decodestring(payload[file]))
-                            part.add_header('Content-Disposition', 'attachment; filename="%s"' % file)
-                            Encoders.encode_base64(part)
-                            payload_part.attach(part)
-                except Exception, error:
-                    logger.notifyChannel(_("Email Template"), netsvc.LOG_ERROR, _("Mail from Account %s failed. Probable Reason:MIME Error\nDescription: %s") % (id, error))
-                    return {'error_msg': _("Server Send Error\nDescription: %s")%error}
-                try:
-                    serv.sendmail(payload_part['From'], addresses_l['all-recipients'], payload_part.as_string())
-                except Exception, error:
-                    logging.getLogger('email_template').error(_("Mail from Account %s failed. Probable Reason: Server Send Error\n Description: %s"), id, error, exc_info=True)
-                    return {'error_msg': _("Server Send Error\nDescription: %s")%error}
-                #The mail sending is complete
-                serv.close()
-                logger.notifyChannel(_("Email Template"), netsvc.LOG_INFO, _("Mail from Account %s successfully Sent.") % (id))
-                return True
-            else:
-                logger.notifyChannel(_("Email Template"), netsvc.LOG_ERROR, _("Mail from Account %s failed. Probable Reason:Account not approved") % id)
-                return {'nodestroy':True,'error_msg': _("Mail from Account %s failed. Probable Reason:Account not approved")% id}
+    def email_send(cr, uid, email_from, email_to, subject, body, model=False, email_cc=None, email_bcc=None, reply_to=False, attach=None,
+            openobject_id=False, ssl=False, subtype='plain', x_headers=None, priority='3', smtp_id=False):
+        attachment_obj = self.pool.get('ir.attachment')
+        email_msg_obj = self.pool.get('email.message')
+        msg_vals = {
+                'name': subject,
+                'model': model or '',
+                'date': time.strftime('%Y-%m-%d'),
+                'user_id': uid,
+                'message': body,
+                'email_from': email_from,
+                'email_to': email_to or '',
+                'email_cc': email_cc or '',
+                'email_bcc': email_bcc or '',
+                'reply_to': reply_to or '',
+                'message_id': openobject_id,
+                'account_id': smtp_id,
+                'sub_type': subtype or '',
+                'x_headers': x_headers or '',
+                'priority': priority,
+                'folder': 'outbox',
+                'state': 'waiting',
+            }
+        email_msg_id = self.create(cr, uid, msg_vals, context)
+        if attach:
+            for attachment in attach:
+                attachment_data = {
+                        'name':  (subject or '') + _(' (Email Attachment)'),
+                        'datas': attachment[1],
+                        'datas_fname': attachment[0],
+                        'description': subject or _('No Description'),
+                        'res_model':'email.message',
+                        'res_id': email_msg_id,
+                    }
+                attachment_id = attachment_obj.create(cr, uid, attachment_data, context)
+                if attachment_id:
+                    email_msg_obj.write(cr, uid, email_msg_id,
+                                      { 'attachments_ids':[(4, attachment_id)] }, context)
+        return True
 
-    def extracttime(self, time_as_string):
-        """
-        TODO: DOC THis
-        """
-        logger = netsvc.Logger()
-        #The standard email dates are of format similar to:
-        #Thu, 8 Oct 2009 09:35:42 +0200
-        date_as_date = False
-        convertor = {'+':1, '-':-1}
-        try:
-            time_as_string = time_as_string.replace(',', '')
-            date_list = time_as_string.split(' ')
-            date_temp_str = ' '.join(date_list[1:5])
-            if len(date_list) >= 6:
-                sign = convertor.get(date_list[5][0], False)
-            else:
-                sign = False
-            try:
-                dt = datetime.datetime.strptime(
-                                            date_temp_str,
-                                            "%d %b %Y %H:%M:%S")
-            except:
-                try:
-                    dt = datetime.datetime.strptime(
-                                            date_temp_str,
-                                            "%d %b %Y %H:%M")
-                except:
-                    return False
-            if sign:
-                try:
-                    offset = datetime.timedelta(
-                                hours=sign * int(
-                                             date_list[5][1:3]
-                                                ),
-                                             minutes=sign * int(
-                                                            date_list[5][3:5]
-                                                                )
-                                                )
-                except Exception, e2:
-                    """Looks like UT or GMT, just forget decoding"""
-                    return False
-            else:
-                offset = datetime.timedelta(hours=0)
-            dt = dt + offset
-            date_as_date = dt.strftime('%Y-%m-%d %H:%M:%S')
-        except Exception, e:
-            logger.notifyChannel(
-                    _("Email Template"),
-                    netsvc.LOG_WARNING,
-                    _(
-                      "Datetime Extraction failed.Date:%s \
-                      \tError:%s") % (
-                                    time_as_string,
-                                    e)
-                      )
-        return date_as_date
 
-    def send_receive(self, cr, uid, ids, context=None):
-        for id in ids:
-            ctx = context.copy()
-            ctx['filters'] = [('account_id', '=', id)]
-            self.pool.get('email.message').send_all_mail(cr, uid, [], context=ctx)
-        return True
 
-    def decode_header_text(self, text):
-        """ Decode internationalized headers RFC2822.
-            To, CC, BCC, Subject fields can contain
-            text slices with different encodes, like:
-                =?iso-8859-1?Q?Enric_Mart=ED?= <enricmarti@company.com>,
-                =?Windows-1252?Q?David_G=F3mez?= <david@company.com>
-            Sometimes they include extra " character at the beginning/
-            end of the contact name, like:
-                "=?iso-8859-1?Q?Enric_Mart=ED?=" <enricmarti@company.com>
-            and decode_header() does not work well, so we use regular
-            expressions (?=   ? ?   ?=) to split the text slices
-        """
-        if not text:
-            return text
-        p = re.compile("(=\?.*?\?.\?.*?\?=)")
-        text2 = ''
-        try:
-            for t2 in p.split(text):
-                text2 += ''.join(
-                            [s.decode(
-                                      t or 'ascii'
-                                    ) for (s, t) in decode_header(t2)]
-                                ).encode('utf-8')
-        except:
-            return text
-        return text2
+#    def get_outgoing_server(self, cursor, user, ids, context=None):
+#        """
+#        Returns the Out Going Connection (SMTP) object
+#
+#        @attention: DO NOT USE except_osv IN THIS METHOD
+#        @param cursor: Database Cursor
+#        @param user: ID of current user
+#        @param ids: ID/list of ids of current object for
+#                    which connection is required
+#                    First ID will be chosen from lists
+#        @param context: Context
+#
+#        @return: SMTP server object or Exception
+#        """
+#        #Type cast ids to integer
+#        if type(ids) == list:
+#            ids = ids[0]
+#        this_object = self.browse(cursor, user, ids, context=context)
+#        if this_object:
+#            if this_object.smtpserver and this_object.smtpport:
+#                try:
+#                    if this_object.smtpssl:
+#                        serv = smtplib.SMTP_SSL(this_object.smtpserver, this_object.smtpport)
+#                    else:
+#                        serv = smtplib.SMTP(this_object.smtpserver, this_object.smtpport)
+#                    if this_object.smtptls:
+#                        serv.ehlo()
+#                        serv.starttls()
+#                        serv.ehlo()
+#                except Exception, error:
+#                    raise error
+#                try:
+#                    if serv.has_extn('AUTH') or this_object.smtpuname or this_object.smtppass:
+#                        serv.login(str(this_object.smtpuname), str(this_object.smtppass))
+#                except Exception, error:
+#                    raise error
+#                return serv
+#            raise Exception(_("SMTP SERVER or PORT not specified"))
+#        raise Exception(_("Core connection for the given ID does not exist"))
+#
+#    def check_outgoing_connection(self, cursor, user, ids, context=None):
+#        """
+#        checks SMTP credentials and confirms if outgoing connection works
+#        (Attached to button)
+#        @param cursor: Database Cursor
+#        @param user: ID of current user
+#        @param ids: list of ids of current object for
+#                    which connection is required
+#        @param context: Context
+#        """
+#        try:
+#            self.get_outgoing_server(cursor, user, ids, context)
+#            raise osv.except_osv(_("SMTP Test Connection Was Successful"), '')
+#        except osv.except_osv, success_message:
+#            raise success_message
+#        except Exception, error:
+#            raise osv.except_osv(
+#                                 _("Out going connection test failed"),
+#                                 _("Reason: %s") % error
+#                                 )
+#
+#    def do_approval(self, cr, uid, ids, context=None):
+#        #TODO: Check if user has rights
+#        self.write(cr, uid, ids, {'state':'approved'}, context=context)
+##        wf_service = netsvc.LocalService("workflow")
+#
+#    def smtp_connection(self, cursor, user, id, context=None):
+#        """
+#        This method should now wrap smtp_connection
+#        """
+#        #This function returns a SMTP server object
+#        logger = netsvc.Logger()
+#        core_obj = self.browse(cursor, user, id, context=context)
+#        if core_obj.smtpserver and core_obj.smtpport and core_obj.state == 'approved':
+#            try:
+#                serv = self.get_outgoing_server(cursor, user, id, context)
+#            except Exception, error:
+#                logger.notifyChannel(_("Email Template"), netsvc.LOG_ERROR, _("Mail from Account %s failed on login. Probable Reason:Could not login to server\nError: %s") % (id, error))
+#                return False
+#            #Everything is complete, now return the connection
+#            return serv
+#        else:
+#            logger.notifyChannel(_("Email Template"), netsvc.LOG_ERROR, _("Mail from Account %s failed. Probable Reason:Account not approved") % id)
+#            return False
+#
+##**************************** MAIL SENDING FEATURES ***********************#
+#    def send_email(self, cr, uid, ids, addresses, subject='', body=None, payload=None, message_id=None, context=None):
+#        #TODO: Replace all this with a single email object
+#        if body is None:
+#            body = {}
+#        if payload is None:
+#            payload = {}
+#        if context is None:
+#            context = {}
+#        logger = netsvc.Logger()
+#        for id in ids:
+#            core_obj = self.browse(cr, uid, id, context)
+#            serv = self.smtp_connection(cr, uid, id)
+#            if serv:
+#                try:
+#                    # Need a multipart/mixed wrapper for attachments if content is alternative
+#                    if payload:
+#                        payload_part = MIMEMultipart(_subtype='mixed')
+#                        text_part = MIMEMultipart(_subtype='mixed')
+#                        payload_part.attach(text_part)
+#                    else:
+#                        # otherwise a single multipart/mixed will do the whole job
+#                        payload_part = text_part = MIMEMultipart(_subtype='mixed')
+#
+#                    if subject:
+#                        payload_part['Subject'] = subject
+#                    from_email = core_obj.email_id
+#                    if '<' in from_email:
+#                        # We have a structured email address, keep it untouched
+#                        payload_part['From'] = Header(core_obj.email_id, 'utf-8').encode()
+#                    else:
+#                        # Plain email address, construct a structured one based on the name:
+#                        sender_name = Header(core_obj.name, 'utf-8').encode()
+#                        payload_part['From'] = sender_name + " <" + core_obj.email_id + ">"
+#                    payload_part['Organization'] = tools.ustr(core_obj.user.company_id.name)
+#                    payload_part['Date'] = formatdate()
+#                    addresses_l = extract_emails_from_dict(addresses)
+#                    if addresses_l['To']:
+#                        payload_part['To'] = u','.join(addresses_l['To'])
+#                    if addresses_l['CC']:
+#                        payload_part['CC'] = u','.join(addresses_l['CC'])
+#                    if addresses_l['Reply-To']:
+#                        payload_part['Reply-To'] = addresses_l['Reply-To'][0]
+#                    if message_id:
+#                        payload_part['Message-ID'] = message_id
+#                    if body.get('text', False):
+#                        temp_body_text = body.get('text', '')
+#                        l = len(temp_body_text.replace(' ', '').replace('\r', '').replace('\n', ''))
+#                        if l == 0:
+#                            body['text'] = u'No Mail Message'
+#                    # Attach parts into message container.
+#                    # According to RFC 2046, the last part of a multipart message, in this case
+#                    # the HTML message, is best and preferred.
+##                    if core_obj.send_pref in ('text', 'mixed', 'alternative'):
+##                        body_text = body.get('text', u'<Empty Message>')
+##                        body_text = tools.ustr(body_text)
+##                        text_part.attach(MIMEText(body_text.encode("utf-8"), _charset='UTF-8'))
+##                    if core_obj.send_pref in ('html', 'mixed', 'alternative'):
+#                    html_body = body.get('html', u'')
+#                    if len(html_body) == 0 or html_body == u'':
+#                        html_body = body.get('text', u'<p>&lt;Empty Message&gt;</p>').replace('\n', '<br/>').replace('\r', '<br/>')
+#                    html_body = tools.ustr(html_body)
+#                    text_part.attach(MIMEText(html_body.encode("utf-8"), _subtype='html', _charset='UTF-8'))
+#
+#                    #Now add attachments if any, wrapping into a container multipart/mixed if needed
+#                    if payload:
+#                        for file in payload:
+#                            part = MIMEBase('application', "octet-stream")
+#                            part.set_payload(base64.decodestring(payload[file]))
+#                            part.add_header('Content-Disposition', 'attachment; filename="%s"' % file)
+#                            Encoders.encode_base64(part)
+#                            payload_part.attach(part)
+#                except Exception, error:
+#                    logger.notifyChannel(_("Email Template"), netsvc.LOG_ERROR, _("Mail from Account %s failed. Probable Reason:MIME Error\nDescription: %s") % (id, error))
+#                    return {'error_msg': _("Server Send Error\nDescription: %s")%error}
+#                try:
+#                    serv.sendmail(payload_part['From'], addresses_l['all-recipients'], payload_part.as_string())
+#                except Exception, error:
+#                    logging.getLogger('email_template').error(_("Mail from Account %s failed. Probable Reason: Server Send Error\n Description: %s"), id, error, exc_info=True)
+#                    return {'error_msg': _("Server Send Error\nDescription: %s")%error}
+#                #The mail sending is complete
+#                serv.close()
+#                logger.notifyChannel(_("Email Template"), netsvc.LOG_INFO, _("Mail from Account %s successfully Sent.") % (id))
+#                return True
+#            else:
+#                logger.notifyChannel(_("Email Template"), netsvc.LOG_ERROR, _("Mail from Account %s failed. Probable Reason:Account not approved") % id)
+#                return {'nodestroy':True,'error_msg': _("Mail from Account %s failed. Probable Reason:Account not approved")% id}
+#
+#    def extracttime(self, time_as_string):
+#        """
+#        TODO: DOC THis
+#        """
+#        logger = netsvc.Logger()
+#        #The standard email dates are of format similar to:
+#        #Thu, 8 Oct 2009 09:35:42 +0200
+#        date_as_date = False
+#        convertor = {'+':1, '-':-1}
+#        try:
+#            time_as_string = time_as_string.replace(',', '')
+#            date_list = time_as_string.split(' ')
+#            date_temp_str = ' '.join(date_list[1:5])
+#            if len(date_list) >= 6:
+#                sign = convertor.get(date_list[5][0], False)
+#            else:
+#                sign = False
+#            try:
+#                dt = datetime.datetime.strptime(
+#                                            date_temp_str,
+#                                            "%d %b %Y %H:%M:%S")
+#            except:
+#                try:
+#                    dt = datetime.datetime.strptime(
+#                                            date_temp_str,
+#                                            "%d %b %Y %H:%M")
+#                except:
+#                    return False
+#            if sign:
+#                try:
+#                    offset = datetime.timedelta(
+#                                hours=sign * int(
+#                                             date_list[5][1:3]
+#                                                ),
+#                                             minutes=sign * int(
+#                                                            date_list[5][3:5]
+#                                                                )
+#                                                )
+#                except Exception, e2:
+#                    """Looks like UT or GMT, just forget decoding"""
+#                    return False
+#            else:
+#                offset = datetime.timedelta(hours=0)
+#            dt = dt + offset
+#            date_as_date = dt.strftime('%Y-%m-%d %H:%M:%S')
+#        except Exception, e:
+#            logger.notifyChannel(
+#                    _("Email Template"),
+#                    netsvc.LOG_WARNING,
+#                    _(
+#                      "Datetime Extraction failed.Date:%s \
+#                      \tError:%s") % (
+#                                    time_as_string,
+#                                    e)
+#                      )
+#        return date_as_date
+#
+#    def send_receive(self, cr, uid, ids, context=None):
+#        for id in ids:
+#            ctx = context.copy()
+#            ctx['filters'] = [('account_id', '=', id)]
+#            self.pool.get('email.message').send_all_mail(cr, uid, [], context=ctx)
+#        return True
+#
+#    def decode_header_text(self, text):
+#        """ Decode internationalized headers RFC2822.
+#            To, CC, BCC, Subject fields can contain
+#            text slices with different encodes, like:
+#                =?iso-8859-1?Q?Enric_Mart=ED?= <enricmarti@company.com>,
+#                =?Windows-1252?Q?David_G=F3mez?= <david@company.com>
+#            Sometimes they include extra " character at the beginning/
+#            end of the contact name, like:
+#                "=?iso-8859-1?Q?Enric_Mart=ED?=" <enricmarti@company.com>
+#            and decode_header() does not work well, so we use regular
+#            expressions (?=   ? ?   ?=) to split the text slices
+#        """
+#        if not text:
+#            return text
+#        p = re.compile("(=\?.*?\?.\?.*?\?=)")
+#        text2 = ''
+#        try:
+#            for t2 in p.split(text):
+#                text2 += ''.join(
+#                            [s.decode(
+#                                      t or 'ascii'
+#                                    ) for (s, t) in decode_header(t2)]
+#                                ).encode('utf-8')
+#        except:
+#            return text
+#        return text2
 
 email_smtp_server()