def message_forward(self, cr, uid, model, thread_ids, msg, email_error=False, context=None): """Sends an email to all people following the given threads. The emails are forwarded immediately, not queued for sending, and not archived. :param str model: thread model :param list thread_ids: ids of the thread records :param msg: email.message.Message object to forward :param email_error: optional email address to notify in case of any delivery error during the forward. :return: True """ model_pool = self.pool.get(model) smtp_server_obj = self.pool.get('ir.mail_server') for res in model_pool.browse(cr, uid, thread_ids, context=context): if hasattr(model_pool, 'message_thread_followers'): followers = model_pool.message_thread_followers( cr, uid, [res.id])[res.id] else: followers = self.message_thread_followers(cr, uid, [res.id])[res.id] message_followers_emails = to_email(','.join( filter(None, followers))) message_recipients = to_email(','.join( filter(None, [ decode(msg['From']), decode(msg['To']), decode(msg['Cc']) ]))) forward_to = [ i for i in message_followers_emails if (i and (i not in message_recipients)) ] if forward_to: # TODO: we need an interface for this for all types of objects, not just leads if hasattr(res, 'section_id'): del msg['Reply-To'] msg['Reply-To'] = res.section_id.reply_to smtp_from, = to_email(msg['From']) del msg['From'], msg['To'], msg['Cc'], msg['Message-Id'] msg['From'] = smtp_from msg['To'] = ", ".join(forward_to) msg['Message-Id'] = tools.generate_tracking_message_id(res.id) if not smtp_server_obj.send_email(cr, uid, msg) and email_error: subj = msg['Subject'] del msg['Subject'], msg['To'], msg['Cc'] msg['Subject'] = _('[OpenERP-Forward-Failed] %s') % subj msg['To'] = email_error smtp_server_obj.send_email(cr, uid, msg) return True
def _message_find_user_id(self, cr, uid, message, context=None): from_local_part = tools.email_split(decode(message.get('From')))[0] # FP Note: canonification required, the minimu: .lower() user_ids = self.pool.get('res.users').search(cr, uid, ['|', ('login', '=', from_local_part), ('email', '=', from_local_part)], context=context) return user_ids[0] if user_ids else uid
def message_forward(self, cr, uid, model, thread_ids, msg, email_error=False, context=None): """Sends an email to all people following the given threads. The emails are forwarded immediately, not queued for sending, and not archived. :param str model: thread model :param list thread_ids: ids of the thread records :param msg: email.message.Message object to forward :param email_error: optional email address to notify in case of any delivery error during the forward. :return: True """ model_pool = self.pool.get(model) smtp_server_obj = self.pool.get('ir.mail_server') for res in model_pool.browse(cr, uid, thread_ids, context=context): if hasattr(model_pool, 'message_thread_followers'): followers = model_pool.message_thread_followers(cr, uid, [res.id])[res.id] else: followers = self.message_thread_followers(cr, uid, [res.id])[res.id] message_followers_emails = to_email(','.join(filter(None, followers))) message_recipients = to_email(','.join(filter(None, [decode(msg['From']), decode(msg['To']), decode(msg['Cc'])]))) forward_to = [i for i in message_followers_emails if (i and (i not in message_recipients))] if forward_to: # TODO: we need an interface for this for all types of objects, not just leads if hasattr(res, 'section_id'): del msg['Reply-To'] msg['Reply-To'] = res.section_id.reply_to smtp_from, = to_email(msg['From']) del msg['From'], msg['To'], msg['Cc'], msg['Message-Id'] msg['From'] = smtp_from msg['To'] = ", ".join(forward_to) msg['Message-Id'] = tools.generate_tracking_message_id(res.id) if not smtp_server_obj.send_email(cr, uid, msg) and email_error: subj = msg['Subject'] del msg['Subject'], msg['To'], msg['Cc'] msg['Subject'] = _('[OpenERP-Forward-Failed] %s') % subj msg['To'] = email_error smtp_server_obj.send_email(cr, uid, msg) return True
def message_parse(self, cr, uid, message, save_original=False, context=None): """Parses a string or email.message.Message representing an RFC-2822 email, and returns a generic dict holding the message details. :param message: the message to parse :type message: email.message.Message | string | unicode :param bool save_original: whether the returned dict should include an ``original`` attachment containing the source of the message :rtype: dict :return: A dict with the following structure, where each field may not be present if missing in original message:: { 'message_id': msg_id, 'subject': subject, 'from': from, 'to': to, 'cc': cc, 'body': unified_body, 'attachments': [('file1', 'bytes'), ('file2', 'bytes')} } """ msg_dict = {} if not isinstance(message, Message): if isinstance(message, unicode): # Warning: message_from_string doesn't always work correctly on unicode, # we must use utf-8 strings here :-( message = message.encode('utf-8') message = email.message_from_string(message) message_id = message['message-id'] if not message_id: # Very unusual situation, be we should be fault-tolerant here message_id = "<%s@localhost>" % time.time() _logger.debug('Parsing Message without message-id, generating a random one: %s', message_id) msg_dict['message_id'] = message_id if 'Subject' in message: msg_dict['subject'] = decode(message.get('Subject')) # Envelope fields not stored in mail.message but made available for message_new() msg_dict['from'] = decode(message.get('from')) msg_dict['to'] = decode(message.get('to')) msg_dict['cc'] = decode(message.get('cc')) if 'From' in message: author_ids = self._message_find_partners(cr, uid, message, ['From'], context=context) if author_ids: msg_dict['author_id'] = author_ids[0] partner_ids = self._message_find_partners(cr, uid, message, ['From', 'To', 'Cc'], context=context) msg_dict['partner_ids'] = partner_ids if 'Date' in message: date_hdr = decode(message.get('Date')) # convert from email timezone to server timezone date_server_datetime = dateutil.parser.parse(date_hdr).astimezone(pytz.timezone(tools.get_server_timezone())) date_server_datetime_str = date_server_datetime.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT) msg_dict['date'] = date_server_datetime_str if 'In-Reply-To' in message: parent_ids = self.pool.get('mail.message').search(cr, uid, [('message_id', '=', decode(message['In-Reply-To']))]) if parent_ids: msg_dict['parent_id'] = parent_ids[0] if 'References' in message and 'parent_id' not in msg_dict: parent_ids = self.pool.get('mail.message').search(cr, uid, [('message_id', 'in', [x.strip() for x in decode(message['References']).split()])]) if parent_ids: msg_dict['parent_id'] = parent_ids[0] msg_dict['body'], msg_dict['attachments'] = self._message_extract_payload(message) return msg_dict
def _message_find_partners(self, cr, uid, message, header_fields=['From'], context=None): """ Find partners related to some header fields of the message. """ s = ', '.join([decode(message.get(h)) for h in header_fields if message.get(h)]) return [partner_id for email in tools.email_split(s) for partner_id in self.pool.get('res.partner').search(cr, uid, [('email', 'ilike', email)], context=context)]