Esempio n. 1
0
 def send(self,
          cr,
          uid,
          ids,
          auto_commit=False,
          raise_exception=False,
          context=None):
     for email in self.pool.get('mail.mail').browse(cr,
                                                    uid,
                                                    ids,
                                                    context=context):
         from_rfc2822 = extract_rfc2822_addresses(email.email_from)[-1]
         server_id = self.pool.get('ir.mail_server').search(
             cr, uid, [('smtp_user', '=', from_rfc2822)], context=context)
         server_id = server_id and server_id[0] or False
         if server_id:
             self.write(cr,
                        uid,
                        ids, {
                            'mail_server_id': server_id,
                            'reply_to': email.email_from,
                        },
                        context=context)
     return super(mail_mail, self).send(cr,
                                        uid,
                                        ids,
                                        auto_commit=auto_commit,
                                        raise_exception=raise_exception,
                                        context=context)
    def send_email(self, cr, uid, message, mail_server_id=None, smtp_server=None, smtp_port=None,
                   smtp_user=None, smtp_password=None, smtp_encryption=None, smtp_debug=False,
                   context=None):

        smtp_from = message['Return-Path'] or message['From']
        assert smtp_from, "The Return-Path or From header is required for any outbound email"

        # The email's "Envelope From" (Return-Path), and all recipient addresses must only contain ASCII characters.
        from_rfc2822 = extract_rfc2822_addresses(smtp_from)
        assert len(from_rfc2822) == 1, "Malformed 'Return-Path' or 'From' address - it may only contain plain ASCII characters"
        smtp_from = from_rfc2822[0]

        #################################################
        # patch: 首先查找 smtp_from 对应的 smtp 服务器
        # 要求 定义 Outgoing Mail Servers 时候, 确保 Description(name) 字段的值 为对应的 邮件发送账户(完整的eamil地址)
        # 本模块以此 为 邮件的发送者 查找 smtp 服务器
        # 需要为系统中 每个可能发送邮件的账户 按以上要求设置一个 服务器

        mail_server_ids = self.search(cr, SUPERUSER_ID, [('name','=',smtp_from)], order='sequence', limit=1)
        if mail_server_ids:
            mail_server = self.browse(cr, SUPERUSER_ID, mail_server_ids[0])
            mail_server_id = mail_server_ids[0]


        res = super(ir_mail_server,self).send_email(cr, uid,
                                                    message,
                                                    mail_server_id,
                                                    smtp_server,
                                                    smtp_port,
                                                    smtp_user,
                                                    smtp_password,
                                                    smtp_encryption,
                                                    smtp_debug,
                                                    context)
        return res
Esempio n. 3
0
    def send(self, auto_commit=False, raise_exception=False):
        ir_mail_server_obj = self.env['ir.mail_server']
        # res_user_obj = self.env['res.users']
        for email in self:
            user = self.env.user  #res_user_obj.search([('partner_id', '=', email.author_id.id)], limit=1)
            if user:
                mail_server = self._get_mail_server()
                #ir_mail_server_obj.search([('user_id', '=', user.id)], limit=1)
                from_rfc2822 = extract_rfc2822_addresses(email.email_from)[-1]
                #
                company_id = self.env['res.company'].search([('email', '=',
                                                              from_rfc2822)])
                if mail_server:
                    if company_id:
                        if company_id.mail_auth_password:
                            mail_server.smtp_user = from_rfc2822
                            mail_server.smtp_pass = company_id.mail_auth_password
                        else:
                            raise osv.except_osv(
                                _("Can`t find any smtp server"),
                                _("请管理员进入“设置-公司”并设置“邮箱授权码”,以保证能正常使用邮箱功能"))
                    else:
                        if user.mail_auth_password:
                            mail_server.smtp_user = user.login
                            mail_server.smtp_pass = user.mail_auth_password
                        else:
                            raise osv.except_osv(
                                _("Can`t find any smtp server"),
                                _("请进入“首选项”并设置“邮箱授权码”,以保证能正常使用邮箱功能"))
                    email.mail_server_id = mail_server.id

                    # email.email_from = email.mail_server_id.replace_email_name(email.email_from)

        return super(linkloving_mail_mail, self).send(auto_commit=False,
                                                      raise_exception=False)
Esempio n. 4
0
 def send_email(self,
                cr,
                uid,
                message,
                mail_server_id=None,
                smtp_server=None,
                smtp_port=None,
                smtp_user=None,
                smtp_password=None,
                smtp_encryption=None,
                smtp_debug=False,
                context=None):
     from_rfc2822 = extract_rfc2822_addresses(message['From'])[-1]
     server_id = self.pool.get('ir.mail_server').search(
         cr, uid, [('smtp_user', '=', from_rfc2822)], context=context)
     if server_id and server_id[0]:
         message['Return-Path'] = from_rfc2822
     return super(ir_mail_server, self).send_email(cr,
                                                   uid,
                                                   message,
                                                   mail_server_id,
                                                   smtp_server,
                                                   smtp_port,
                                                   smtp_user,
                                                   smtp_password,
                                                   smtp_encryption,
                                                   smtp_debug,
                                                   context=context)
Esempio n. 5
0
 def send(self,
          cr,
          uid,
          ids,
          auto_commit=False,
          raise_exception=False,
          context=None):
     for email in self.pool.get('mail.mail').browse(cr,
                                                    uid,
                                                    ids,
                                                    context=context):
         from_rfc2822 = extract_rfc2822_addresses(email.email_from)[-1]
         server_ids = self.pool.get('ir.mail_server').search(
             cr, uid, [('sequence', '<', 11)], context=context)
         print "server ids>>>>>>>>>>>>>>>>>>>>>", server_ids
         server_id = False
         if server_ids:
             server_id = rd.choice(server_ids)
         print "server id>>>>>>>>>>>>>>>>>", server_id
         if server_id:
             self.write(cr,
                        uid,
                        ids, {
                            'mail_server_id': server_id,
                            'reply_to': email.email_from,
                        },
                        context=context)
     return super(mail_mail, self).send(cr,
                                        uid,
                                        ids,
                                        auto_commit=auto_commit,
                                        raise_exception=raise_exception,
                                        context=context)
Esempio n. 6
0
 def send(self, auto_commit=False, raise_exception=False):
     for email in self:
         from_rfc2822 = extract_rfc2822_addresses(email.email_from)[-1]
         server_id = self.env['ir.mail_server'].search([('smtp_user', '=',
                                                         from_rfc2822)])
         server_id = server_id and server_id[0].id or False
         if server_id:
             email.write({
                 'mail_server_id': server_id,
                 'reply_to': email.email_from
             })
     return super(mail_mail, self).send(auto_commit=auto_commit,
                                        raise_exception=raise_exception)
Esempio n. 7
0
    def send_email(self,
                   cr,
                   uid,
                   message,
                   mail_server_id=None,
                   smtp_server=None,
                   smtp_port=None,
                   smtp_user=None,
                   smtp_password=None,
                   smtp_encryption=None,
                   smtp_debug=False,
                   context=None):

        print '*************************'

        smtp_from = message['Return-Path'] or message['From']
        assert smtp_from, "The Return-Path or From header is required for any outbound email"

        # The email's "Envelope From" (Return-Path), and all recipient addresses must only contain ASCII characters.
        from_rfc2822 = extract_rfc2822_addresses(smtp_from)
        assert len(
            from_rfc2822
        ) == 1, "Malformed 'Return-Path' or 'From' address - it may only contain plain ASCII characters"
        smtp_from = from_rfc2822[0]

        #################################################
        # patch: 首先查找 smtp_from 对应的 smtp 服务器
        # 要求 定义 Outgoing Mail Servers 时候, 确保 Description(name) 字段的值 为对应的 邮件发送账户(完整的eMail地址)
        # 本模块以此 为 邮件的发送者 查找 smtp 服务器
        # 需要为系统中 每个可能发送邮件的账户 按以上要求设置一个 服务器

        mail_server_ids = self.search(cr,
                                      SUPERUSER_ID, [('name', '=', smtp_from)],
                                      order='sequence',
                                      limit=1)
        if mail_server_ids:
            mail_server = self.browse(cr, SUPERUSER_ID, mail_server_ids[0])
            mail_server_id = mail_server_ids[0]

            #change the header to adpater 163.com
            message['Return-Path'] = mail_server.smtp_user

        res = super(ir_mail_server,
                    self).send_email(cr, uid, message, mail_server_id,
                                     smtp_server, smtp_port, smtp_user,
                                     smtp_password, smtp_encryption,
                                     smtp_debug, context)
        return res
Esempio n. 8
0
 def send_email(self,
                message,
                mail_server_id=None,
                smtp_server=None,
                smtp_port=None,
                smtp_user=None,
                smtp_password=None,
                smtp_encryption=None,
                smtp_debug=False):
     from_rfc2822 = extract_rfc2822_addresses(message['From'])[-1]
     server_id = self.env['ir.mail_server'].search([('smtp_user', '=',
                                                     from_rfc2822)])
     server_id = server_id and server_id[0].id or False
     if server_id:
         message['Return-Path'] = from_rfc2822
     return super(ir_mail_server,
                  self).send_email(message, mail_server_id, smtp_server,
                                   smtp_port, smtp_user, smtp_password,
                                   smtp_encryption, smtp_debug)
 def send_email(self,
                cr,
                uid,
                message,
                mail_server_id=None,
                smtp_server=None,
                smtp_port=None,
                smtp_user=None,
                smtp_password=None,
                smtp_encryption=None,
                smtp_debug=False,
                context=None):
     override_email = self.pool['ir.model.data'].xmlid_to_object(
         cr,
         uid,
         'override_mail_recipients.override_email_to',
         raise_if_not_found=True,
         context=context).value
     if override_email:
         for field in ['to', 'cc', 'bcc']:
             if not message[field]:
                 continue
             original = COMMASPACE.join(message.get_all(field, []))
             del message[field]
             message[field] = COMMASPACE.join(
                 '"%s" <%s>' %
                 (original.replace('\\', '').replace('"', '\\"').replace(
                     '<', '[').replace('>', ']').replace('@', '(at)'),
                  email)
                 for email in extract_rfc2822_addresses(override_email))
     return super(IrMailServer,
                  self).send_email(cr,
                                   uid,
                                   message,
                                   mail_server_id=mail_server_id,
                                   smtp_server=smtp_server,
                                   smtp_port=smtp_port,
                                   smtp_user=smtp_user,
                                   smtp_password=smtp_password,
                                   smtp_encryption=smtp_encryption,
                                   smtp_debug=smtp_debug,
                                   context=context)
    def send_email(self, cr, uid, message, mail_server_id=None, smtp_server=None, smtp_port=None,
                   smtp_user=None, smtp_password=None, smtp_encryption=None, smtp_debug=False,
                   context=None):
        """Sends an email directly (no queuing).

        No retries are done, the caller should handle MailDeliveryException in order to ensure that
        the mail is never lost.

        If the mail_server_id is provided, sends using this mail server, ignoring other smtp_* arguments.
        If mail_server_id is None and smtp_server is None, use the default mail server (highest priority).
        If mail_server_id is None and smtp_server is not None, use the provided smtp_* arguments.
        If both mail_server_id and smtp_server are None, look for an 'smtp_server' value in server config,
        and fails if not found.

        :param message: the email.message.Message to send. The envelope sender will be extracted from the
                        ``Return-Path`` or ``From`` headers. The envelope recipients will be
                        extracted from the combined list of ``To``, ``CC`` and ``BCC`` headers.
        :param mail_server_id: optional id of ir.mail_server to use for sending. overrides other smtp_* arguments.
        :param smtp_server: optional hostname of SMTP server to use
        :param smtp_encryption: optional TLS mode, one of 'none', 'starttls' or 'ssl' (see ir.mail_server fields for explanation)
        :param smtp_port: optional SMTP port, if mail_server_id is not passed
        :param smtp_user: optional SMTP user, if mail_server_id is not passed
        :param smtp_password: optional SMTP password to use, if mail_server_id is not passed
        :param smtp_debug: optional SMTP debug flag, if mail_server_id is not passed
        :return: the Message-ID of the message that was just sent, if successfully sent, otherwise raises
                 MailDeliveryException and logs root cause.
        """
        smtp_from = message['Return-Path'] or message['From']
        assert smtp_from, "The Return-Path or From header is required for any outbound email"

        # The email's "Envelope From" (Return-Path), and all recipient addresses must only contain ASCII characters.
        from_rfc2822 = extract_rfc2822_addresses(smtp_from)
        assert len(from_rfc2822) == 1, "Malformed 'Return-Path' or 'From' address - it may only contain plain ASCII characters"
        smtp_from = from_rfc2822[0]
        email_to = message['To']
        email_cc = message['Cc']
        email_bcc = message['Bcc']
        smtp_to_list = filter(None, tools.flatten(map(extract_rfc2822_addresses,[email_to, email_cc, email_bcc])))
        assert smtp_to_list, "At least one valid recipient address should be specified for outgoing emails (To/Cc/Bcc)"

        # Do not actually send emails in testing mode!
        if getattr(threading.currentThread(), 'testing', False):
            _logger.log(logging.TEST, "skip sending email in test mode")
            return message['Message-Id']

        # Get SMTP Server Details from Mail Server
        mail_server = None
        if mail_server_id:
            mail_server = self.browse(cr, SUPERUSER_ID, mail_server_id)
        elif not smtp_server:
            mail_server_ids = self.search(cr, SUPERUSER_ID, [], order='sequence', limit=1)
            if mail_server_ids:
                mail_server = self.browse(cr, SUPERUSER_ID, mail_server_ids[0])

        if mail_server:
            smtp_server = mail_server.smtp_host
            smtp_user = mail_server.smtp_user
            smtp_password = mail_server.smtp_pass
            smtp_port = mail_server.smtp_port
            smtp_encryption = mail_server.smtp_encryption
            smtp_debug = smtp_debug or mail_server.smtp_debug
        else:
            # we were passed an explicit smtp_server or nothing at all
            smtp_server = smtp_server or tools.config.get('smtp_server')
            smtp_port = tools.config.get('smtp_port', 25) if smtp_port is None else smtp_port
            smtp_user = smtp_user or tools.config.get('smtp_user')
            smtp_password = smtp_password or tools.config.get('smtp_password')
            if smtp_encryption is None and tools.config.get('smtp_ssl'):
                smtp_encryption = 'starttls' # STARTTLS is the new meaning of the smtp_ssl flag as of v7.0
                
        #update by frank
        #smtp_user = smtp_from
        pid = self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id._id
        smtp_user = self.pool.get('res.partner').browse(cr, uid, pid, context=context).email
        smtp_password = self.pool.get('res.users').browse(cr, uid, uid, context=context).x_mailpass
        #/update
        
        if not smtp_server:
            raise osv.except_osv(
                         _("Missing SMTP Server"),
                         _("Please define at least one SMTP server, or provide the SMTP parameters explicitly."))

        try:
            message_id = message['Message-Id']

            # Add email in Maildir if smtp_server contains maildir.
            if smtp_server.startswith('maildir:/'):
                from mailbox import Maildir
                maildir_path = smtp_server[8:]
                mdir = Maildir(maildir_path, factory=None, create = True)
                mdir.add(message.as_string(True))
                return message_id

            try:
                smtp = self.connect(smtp_server, smtp_port, smtp_user, smtp_password, smtp_encryption or False, smtp_debug)
                #smtp = self.connect(smtp_server, smtp_port, smtp_from, smtp_password, smtp_encryption or False, smtp_debug)
                smtp.sendmail(smtp_from, smtp_to_list, message.as_string())
            finally:
                try:
                    # Close Connection of SMTP Server
                    smtp.quit()
                except Exception:
                    # ignored, just a consequence of the previous exception
                    pass
        except Exception, e:
            msg = _("Mail delivery failed via SMTP server '%s'.\n%s: %s") % (tools.ustr(smtp_server),
                                                                             e.__class__.__name__,
                                                                             tools.ustr(e))
            _logger.exception(msg)
            raise MailDeliveryException(_("Mail delivery failed"), msg)
Esempio n. 11
0
    def send_email(self,
                   cr,
                   uid,
                   message,
                   mail_server_id=None,
                   smtp_server=None,
                   smtp_port=None,
                   smtp_user=None,
                   smtp_password=None,
                   smtp_encryption=None,
                   smtp_debug=False,
                   context=None):
        """Sends an email directly (no queuing).

        No retries are done, the caller should handle MailDeliveryException in order to ensure that
        the mail is never lost.

        If the mail_server_id is provided, sends using this mail server, ignoring other smtp_* arguments.
        If mail_server_id is None and smtp_server is None, use the default mail server (highest priority).
        If mail_server_id is None and smtp_server is not None, use the provided smtp_* arguments.
        If both mail_server_id and smtp_server are None, look for an 'smtp_server' value in server config,
        and fails if not found.

        :param message: the email.message.Message to send. The envelope sender will be extracted from the
                        ``Return-Path`` or ``From`` headers. The envelope recipients will be
                        extracted from the combined list of ``To``, ``CC`` and ``BCC`` headers.
        :param mail_server_id: optional id of ir.mail_server to use for sending. overrides other smtp_* arguments.
        :param smtp_server: optional hostname of SMTP server to use
        :param smtp_encryption: optional TLS mode, one of 'none', 'starttls' or 'ssl' (see ir.mail_server fields for explanation)
        :param smtp_port: optional SMTP port, if mail_server_id is not passed
        :param smtp_user: optional SMTP user, if mail_server_id is not passed
        :param smtp_password: optional SMTP password to use, if mail_server_id is not passed
        :param smtp_debug: optional SMTP debug flag, if mail_server_id is not passed
        :return: the Message-ID of the message that was just sent, if successfully sent, otherwise raises
                 MailDeliveryException and logs root cause.
        """
        smtp_from = message['Return-Path'] or message['From']
        assert smtp_from, "The Return-Path or From header is required for any outbound email"

        # The email's "Envelope From" (Return-Path), and all recipient addresses must only contain ASCII characters.
        from_rfc2822 = extract_rfc2822_addresses(smtp_from)
        assert from_rfc2822, (
            "Malformed 'Return-Path' or 'From' address: %r - "
            "It should contain one valid plain ASCII email") % smtp_from
        # use last extracted email, to support rarities like 'Support@MyComp <*****@*****.**>'
        smtp_from = from_rfc2822[-1]
        email_to = message['To']
        email_cc = message['Cc']
        email_bcc = message['Bcc']

        smtp_to_list = filter(
            None,
            tools.flatten(
                map(extract_rfc2822_addresses,
                    [email_to, email_cc, email_bcc])))
        assert smtp_to_list, "At least one valid recipient address should be specified for outgoing emails (To/Cc/Bcc)"

        # Do not actually send emails in testing mode!
        if getattr(threading.currentThread(), 'testing', False):
            _test_logger.info("skip sending email in test mode")
            return message['Message-Id']

        # Get SMTP Server Details from Mail Server
        mail_server = None
        if mail_server_id:
            mail_server = self.browse(cr, SUPERUSER_ID, mail_server_id)
        elif not smtp_server:
            mail_server_ids = self.search(cr,
                                          SUPERUSER_ID, [],
                                          order='sequence',
                                          limit=1)
            if mail_server_ids:
                mail_server = self.browse(cr, SUPERUSER_ID, mail_server_ids[0])

        if mail_server:
            smtp_server = mail_server.smtp_host
            smtp_user = mail_server.smtp_user
            smtp_password = mail_server.smtp_pass
            smtp_port = mail_server.smtp_port
            smtp_encryption = mail_server.smtp_encryption
            smtp_debug = smtp_debug or mail_server.smtp_debug
        else:
            # we were passed an explicit smtp_server or nothing at all
            smtp_server = smtp_server or tools.config.get('smtp_server')
            smtp_port = tools.config.get(
                'smtp_port', 25) if smtp_port is None else smtp_port
            smtp_user = smtp_user or tools.config.get('smtp_user')
            smtp_password = smtp_password or tools.config.get('smtp_password')
            if smtp_encryption is None and tools.config.get('smtp_ssl'):
                smtp_encryption = 'starttls'  # STARTTLS is the new meaning of the smtp_ssl flag as of v7.0

        #NG: Only Save Bcc in smtp_to_list
        if message.get('Bcc', False):
            del message['Bcc']

        if not smtp_server:
            raise osv.except_osv(
                _("Missing SMTP Server"),
                _("Please define at least one SMTP server, or provide the SMTP parameters explicitly."
                  ))

        try:
            message_id = message['Message-Id']

            # Add email in Maildir if smtp_server contains maildir.
            if smtp_server.startswith('maildir:/'):
                from mailbox import Maildir
                maildir_path = smtp_server[8:]
                mdir = Maildir(maildir_path, factory=None, create=True)
                mdir.add(message.as_string(True))
                return message_id

            try:
                smtp = self.connect(smtp_server, smtp_port, smtp_user,
                                    smtp_password, smtp_encryption or False,
                                    smtp_debug)
                smtp.sendmail(smtp_from, smtp_to_list, message.as_string())
            finally:
                try:
                    # Close Connection of SMTP Server
                    smtp.quit()
                except Exception:
                    # ignored, just a consequence of the previous exception
                    pass
        except Exception, e:
            msg = _("Mail delivery failed via SMTP server '%s'.\n%s: %s") % (
                tools.ustr(smtp_server), e.__class__.__name__, tools.ustr(e))
            _logger.exception(msg)
            raise MailDeliveryException(_("Mail Delivery Failed"), msg)
Esempio n. 12
0
    def send_email(self,
                   message,
                   mail_server_id=None,
                   smtp_server=None,
                   smtp_port=None,
                   smtp_user=None,
                   smtp_password=None,
                   smtp_encryption=None,
                   smtp_debug=False,
                   context=None):
        from_rfc2822 = extract_rfc2822_addresses(message['From'])[-1]
        server_id = self.env['ir.mail_server'].search([
            '|', ('id', '=', self.env.user.send_mail_server_id.id),
            ('id', '=', self.env.user.company_id.send_mail_server_id.id)
        ],
                                                      order='sequence',
                                                      limit=1)
        #.search( [('smtp_user', '=', from_rfc2822)],)
        if server_id and server_id[0]:
            message['Return-Path'] = from_rfc2822

        smtp_from = message['Return-Path']
        if not smtp_from:
            smtp_from = self._get_default_bounce_address(context=context)
        if not smtp_from:
            smtp_from = message['From']
        assert smtp_from, "The Return-Path or From header is required for any outbound email"

        # The email's "Envelope From" (Return-Path), and all recipient addresses must only contain ASCII characters.
        from_rfc2822 = extract_rfc2822_addresses(smtp_from)
        assert from_rfc2822, (
            "Malformed 'Return-Path' or 'From' address: %r - "
            "It should contain one valid plain ASCII email") % smtp_from
        # use last extracted email, to support rarities like 'Support@MyComp <*****@*****.**>'
        smtp_from = from_rfc2822[-1]
        email_to = message['To']
        email_cc = message['Cc']
        email_bcc = message['Bcc']

        smtp_to_list = filter(
            None,
            tools.flatten(
                map(extract_rfc2822_addresses,
                    [email_to, email_cc, email_bcc])))
        assert smtp_to_list, self.NO_VALID_RECIPIENT

        x_forge_to = message['X-Forge-To']
        if x_forge_to:
            # `To:` header forged, e.g. for posting on mail.groups, to avoid confusion
            del message['X-Forge-To']
            del message['To']  # avoid multiple To: headers!
            message['To'] = x_forge_to

        # Do not actually send emails in testing mode!
        if getattr(threading.currentThread(), 'testing', False):
            _test_logger.info("skip sending email in test mode")
            return message['Message-Id']

        # Get SMTP Server Details from Mail Server
        mail_server = None
        if mail_server_id:
            mail_server = self.browse(mail_server_id)
        elif not smtp_server:
            mail_server_ids = self.search([], order='sequence', limit=1)
            if mail_server_ids:
                mail_server = self.browse(mail_server_ids[0])

        if mail_server:
            smtp_server = mail_server.smtp_host
            smtp_user = mail_server.smtp_user
            smtp_password = mail_server.smtp_pass
            smtp_port = mail_server.smtp_port
            smtp_encryption = mail_server.smtp_encryption
            smtp_debug = smtp_debug or mail_server.smtp_debug
        else:
            # we were passed an explicit smtp_server or nothing at all
            smtp_server = smtp_server or tools.config.get('smtp_server')
            smtp_port = tools.config.get(
                'smtp_port', 25) if smtp_port is None else smtp_port
            smtp_user = smtp_user or tools.config.get('smtp_user')
            smtp_password = smtp_password or tools.config.get('smtp_password')
            if smtp_encryption is None and tools.config.get('smtp_ssl'):
                smtp_encryption = 'starttls'  # STARTTLS is the new meaning of the smtp_ssl flag as of v7.0

        if not smtp_server:
            raise osv.except_osv(
                _("Missing SMTP Server"),
                _("Please define at least one SMTP server, or provide the SMTP parameters explicitly."
                  ))

        try:
            message_id = message['Message-Id']

            # Add email in Maildir if smtp_server contains maildir.
            if smtp_server.startswith('maildir:/'):
                from mailbox import Maildir
                maildir_path = smtp_server[8:]
                mdir = Maildir(maildir_path, factory=None, create=True)
                mdir.add(message.as_string(True))
                return message_id

            smtp = None
            try:
                smtp = self.connect(smtp_server, smtp_port, smtp_user,
                                    smtp_password, smtp_encryption or False,
                                    smtp_debug)
                smtp.sendmail(smtp_from, smtp_to_list, message.as_string())
            finally:
                if smtp is not None:
                    smtp.quit()
        except Exception, e:
            msg = _(
                "Mail delivery failed via SMTP server '%s'.\n%s: %s, Please check your mail setting"
            ) % (tools.ustr(smtp_server), e.__class__.__name__, tools.ustr(e))
            raise osv.except_osv(_("Mail Delivery Failed"), msg)
Esempio n. 13
0
def send_email(
    self,
    cr,
    uid,
    message,
    mail_server_id=None,
    smtp_server=None,
    smtp_port=None,
    smtp_user=None,
    smtp_password=None,
    smtp_encryption=None,
    smtp_debug=False,
    context=None,
):
    """Sends an email directly (no queuing).

    No retries are done, the caller should handle MailDeliveryException in order to ensure that
    the mail is never lost.

    If the mail_server_id is provided, sends using this mail server, ignoring other smtp_* arguments.
    If mail_server_id is None and smtp_server is None, use the default mail server (highest priority).
    If mail_server_id is None and smtp_server is not None, use the provided smtp_* arguments.
    If both mail_server_id and smtp_server are None, look for an 'smtp_server' value in server config,
    and fails if not found.

    :param message: the email.message.Message to send. The envelope sender will be extracted from the
                    ``Return-Path`` or ``From`` headers. The envelope recipients will be
                    extracted from the combined list of ``To``, ``CC`` and ``BCC`` headers.
    :param mail_server_id: optional id of ir.mail_server to use for sending. overrides other smtp_* arguments.
    :param smtp_server: optional hostname of SMTP server to use
    :param smtp_encryption: optional TLS mode, one of 'none', 'starttls' or 'ssl' (see ir.mail_server fields for explanation)
    :param smtp_port: optional SMTP port, if mail_server_id is not passed
    :param smtp_user: optional SMTP user, if mail_server_id is not passed
    :param smtp_password: optional SMTP password to use, if mail_server_id is not passed
    :param smtp_debug: optional SMTP debug flag, if mail_server_id is not passed
    :return: the Message-ID of the message that was just sent, if successfully sent, otherwise raises
             MailDeliveryException and logs root cause.
    """
    smtp_from = message["Return-Path"] or message["From"]
    assert smtp_from, "The Return-Path or From header is required for any outbound email"

    # The email's "Envelope From" (Return-Path), and all recipient addresses must only contain ASCII characters.
    from_rfc2822 = extract_rfc2822_addresses(smtp_from)
    assert from_rfc2822, (
        "Malformed 'Return-Path' or 'From' address: %r - " "It should contain one valid plain ASCII email"
    ) % smtp_from
    # use last extracted email, to support rarities like 'Support@MyComp <*****@*****.**>'
    smtp_from = from_rfc2822[-1]
    email_to = message["To"]
    email_cc = message["Cc"]
    email_bcc = message["Bcc"]
    smtp_to_list = filter(None, tools.flatten(map(extract_rfc2822_addresses, [email_to, email_cc, email_bcc])))
    assert smtp_to_list, self.NO_VALID_RECIPIENT

    # Do not actually send emails in testing mode!
    if getattr(threading.currentThread(), "testing", False):
        _logger.log(logging.INFO, "skip sending email in test mode")
        return message["Message-Id"]

    # Get SMTP Server Details from Mail Server
    mail_server = None
    if mail_server_id:
        mail_server = self.browse(cr, SUPERUSER_ID, mail_server_id)
    elif not smtp_server:
        mail_server_ids = self.search(cr, SUPERUSER_ID, [], order="sequence", limit=1)
        if mail_server_ids:
            mail_server = self.browse(cr, SUPERUSER_ID, mail_server_ids[0])

    if mail_server:
        smtp_server = mail_server.smtp_host
        smtp_user = mail_server.smtp_user
        smtp_password = mail_server.smtp_pass
        smtp_port = mail_server.smtp_port
        smtp_encryption = mail_server.smtp_encryption
        smtp_debug = smtp_debug or mail_server.smtp_debug
    else:
        # we were passed an explicit smtp_server or nothing at all
        smtp_server = smtp_server or tools.config.get("smtp_server")
        smtp_port = tools.config.get("smtp_port", 25) if smtp_port is None else smtp_port
        smtp_user = smtp_user or tools.config.get("smtp_user")
        smtp_password = smtp_password or tools.config.get("smtp_password")
        if smtp_encryption is None and tools.config.get("smtp_ssl"):
            smtp_encryption = "starttls"  # STARTTLS is the new meaning of the smtp_ssl flag as of v7.0

    if not smtp_server:
        raise osv.except_osv(
            _("Missing SMTP Server"),
            _("Please define at least one SMTP server, or provide the SMTP parameters explicitly."),
        )

    try:
        message_id = message["Message-Id"]

        # Add email in Maildir if smtp_server contains maildir.
        if smtp_server.startswith("maildir:/"):
            from mailbox import Maildir

            maildir_path = smtp_server[8:]
            mdir = Maildir(maildir_path, factory=None, create=True)
            mdir.add(message.as_string(True))
            return message_id

        try:
            smtp = self.connect(smtp_server, smtp_port, smtp_user, smtp_password, smtp_encryption or False, smtp_debug)
            # smtp.sendmail(smtp_from, smtp_to_list, message.as_string())
            """
            johnw 02/18/2014 enhance the mail sending logic
            to handle the "login and from address not mathcing" issue, 
            for example, 163.com will raise exception under this case
            if from and login user is different, then to try to send using smtp_user again  
            """
            try:
                smtp.sendmail(smtp_from, smtp_to_list, message.as_string())
            except Exception, e:
                if smtp_from != smtp_user:
                    smtp.sendmail(smtp_user, smtp_to_list, message.as_string())
                else:
                    raise e
        finally:
            try:
                # Close Connection of SMTP Server
                smtp.quit()
            except Exception:
                # ignored, just a consequence of the previous exception
                pass
    except Exception, e:
        msg = _("Mail delivery failed via SMTP server '%s'.\n%s: %s") % (
            tools.ustr(smtp_server),
            e.__class__.__name__,
            tools.ustr(e),
        )
        _logger.exception(msg)
        raise MailDeliveryException(_("Mail delivery failed"), msg)
Esempio n. 14
0
    def send_email(self,
                   cr,
                   uid,
                   message,
                   mail_server_id=None,
                   smtp_server=None,
                   smtp_port=None,
                   smtp_user=None,
                   smtp_password=None,
                   smtp_encryption=None,
                   smtp_debug=False,
                   context=None):
        """Override the standard method to fix the issue of using a mail
        client where relaying is disallowed."""
        # Use the default bounce address **only if** no Return-Path was
        # provided by caller.  Caller may be using Variable Envelope Return
        # Path (VERP) to detect no-longer valid email addresses.
        smtp_from = message['Return-Path']
        if not smtp_from:
            smtp_from = self._get_default_bounce_address(cr,
                                                         uid,
                                                         context=context)
        if not smtp_from:
            smtp_from = message['From']
        assert smtp_from, (
            "The Return-Path or From header is required for any outbound email"
        )

        # The email's "Envelope From" (Return-Path), and all recipient
        # addresses must only contain ASCII characters.
        from_rfc2822 = extract_rfc2822_addresses(smtp_from)
        assert from_rfc2822, (
            "Malformed 'Return-Path' or 'From' address: %r - "
            "It should contain one valid plain ASCII email") % smtp_from
        # use last extracted email, to support rarities like
        # 'Support@MyComp <*****@*****.**>'
        smtp_from = from_rfc2822[-1]
        email_to = message['To']
        email_cc = message['Cc']
        email_bcc = message['Bcc']

        smtp_to_list = filter(
            None,
            tools.flatten(
                map(extract_rfc2822_addresses,
                    [email_to, email_cc, email_bcc])))
        assert smtp_to_list, self.NO_VALID_RECIPIENT

        x_forge_to = message['X-Forge-To']
        if x_forge_to:
            # `To:` header forged, e.g. for posting on mail.groups,
            # to avoid confusion
            del message['X-Forge-To']
            del message['To']  # avoid multiple To: headers!
            message['To'] = x_forge_to

        # Do not actually send emails in testing mode!
        if getattr(threading.currentThread(), 'testing', False):
            _test_logger.info("skip sending email in test mode")
            return message['Message-Id']

        # Get SMTP Server Details from Mail Server
        mail_server = None
        if mail_server_id:
            mail_server = self.browse(cr, SUPERUSER_ID, mail_server_id)
        elif not smtp_server:
            mail_server_ids = self.search(cr,
                                          SUPERUSER_ID, [],
                                          order='sequence',
                                          limit=1)
            if mail_server_ids:
                mail_server = self.browse(cr, SUPERUSER_ID, mail_server_ids[0])

        if mail_server:
            smtp_server = mail_server.smtp_host
            smtp_user = mail_server.smtp_user
            smtp_password = mail_server.smtp_pass
            smtp_port = mail_server.smtp_port
            smtp_encryption = mail_server.smtp_encryption
            smtp_debug = smtp_debug or mail_server.smtp_debug
        else:
            # we were passed an explicit smtp_server or nothing at all
            smtp_server = smtp_server or tools.config.get('smtp_server')
            smtp_port = tools.config.get(
                'smtp_port', 25) if smtp_port is None else smtp_port
            smtp_user = smtp_user or tools.config.get('smtp_user')
            smtp_password = smtp_password or tools.config.get('smtp_password')
            if smtp_encryption is None and tools.config.get('smtp_ssl'):
                smtp_encryption = 'starttls'
                # STARTTLS is the new meaning of the smtp_ssl flag as of v7.0

        if not smtp_server:
            raise osv.except_osv(
                _("Missing SMTP Server"),
                _("Please define at least one SMTP server, or "
                  "provide the SMTP parameters explicitly."))

        try:
            message_id = message['Message-Id']

            # Add email in Maildir if smtp_server contains maildir.
            if smtp_server.startswith('maildir:/'):
                from mailbox import Maildir
                maildir_path = smtp_server[8:]
                mdir = Maildir(maildir_path, factory=None, create=True)
                mdir.add(message.as_string(True))
                return message_id

            smtp = None
            try:
                # START OF CODE ADDED
                smtp = self.connect(smtp_server, smtp_port, smtp_user,
                                    smtp_password, smtp_encryption or False,
                                    smtp_debug)
                # smtp.sendmail(smtp_from, smtp_to_list, message.as_string())

                from email.utils import parseaddr, formataddr
                # exact name and address
                (oldname, oldemail) = parseaddr(message['From'])
                # use original name with new address
                newfrom = formataddr((oldname, smtp_user))
                # need to use replace_header instead '=' to prevent
                # double field
                message.replace_header('From', newfrom)
                smtp.sendmail(smtp_user, smtp_to_list, message.as_string())
                # END OF CODE ADDED
            finally:
                if smtp is not None:
                    smtp.quit()
        except Exception, e:
            msg = _("Mail delivery failed via SMTP server '%s'.\n%s: %s") % (
                tools.ustr(smtp_server), e.__class__.__name__, tools.ustr(e))
            _logger.error(msg)
            raise MailDeliveryException(_("Mail Delivery Failed"), msg)