[FIX] crm, mail_gateway: review, cleanup and improvements in mail_gateway and crm

bzr revid: odo@openerp.com-20100625174141-an257bdq3yjyagse
This commit is contained in:
Olivier Dony 2010-06-25 19:41:41 +02:00
parent cc1a9c21d1
commit 1c2af052b2
7 changed files with 142 additions and 139 deletions

View File

@ -96,20 +96,20 @@ class crm_lead(osv.osv, crm_case):
_columns = {
# From crm.case
'name': fields.char('Name', size=64),
'active': fields.boolean('Active', required=False),
'name': fields.char('Name', size=64),
'active': fields.boolean('Active', required=False),
'date_action_last': fields.datetime('Last Action', readonly=1),
'date_action_next': fields.datetime('Next Action', readonly=1),
'email_from': fields.char('Email', size=128, help="These people will receive email."),
'email_from': fields.char('Email', size=128, help="E-mail address of the contact"),
'section_id': fields.many2one('crm.case.section', 'Sales Team', \
select=True, help='Sales team to which Case belongs to.\
Define Responsible user and Email account for mail gateway.'),
select=True, help='Sales team to which this case belongs to.\
Defines responsible user and e-mail address for the mail gateway.'),
'create_date': fields.datetime('Creation Date' , readonly=True),
'email_cc': fields.text('Watchers Emails', size=252 , help="These \
people will receive a copy of the future communication between partner \
and users by email"),
addresses will receive a copy of the future e-mail communication between partner \
and users"),
'description': fields.text('Notes'),
'write_date': fields.datetime('Update Date' , readonly=True),
'write_date': fields.datetime('Update Date' , readonly=True),
# Lead fields
'categ_id': fields.many2one('crm.case.categ', 'Lead Source', \
@ -274,8 +274,8 @@ and users by email"),
res = mailgate_pool.get_partner(cr, uid, msg.get('from') or msg.get_unixfrom())
if res:
vals.update(res)
res = self.create(cr, uid, vals, context)
res = self.create(cr, uid, vals, context)
attachents = msg.get('attachments', [])
for attactment in attachents or []:
@ -318,14 +318,22 @@ and users by email"),
if res and maps.get(res.group(1).lower()):
key = maps.get(res.group(1).lower())
vls[key] = res.group(2).lower()
vals.update(vls)
res = self.write(cr, uid, ids, vals)
# Unfortunately the API is based on lists
# but we want to update the state based on the
# previous state, so we have to loop:
for case in self.browse(cr, uid, ids, context=context):
values = dict(vals)
if case.state == crm.AVAILABLE_STATES[4][0]: #pending
values.update(state=crm.AVAILABLE_STATES[1][0]) #open
res = self.write(cr, uid, [case.id], values, context=context)
return res
def emails_get(self, cr, uid, ids, context=None):
"""
"""
Get Emails
@param self: The object pointer
@param cr: the current row, from the database cursor,

View File

@ -109,7 +109,7 @@ class crm_opportunity(osv.osv):
_defaults = {
'company_id': lambda s,cr,uid,c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.lead', context=c),
'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0],
'priority': crm.AVAILABLE_PRIORITIES[2][0],
}
def action_makeMeeting(self, cr, uid, ids, context=None):

View File

@ -20,10 +20,12 @@
#
##############################################################################
from osv import osv, fields
import base64
import itertools
from tools.translate import _
from osv import osv, fields
import tools
from tools.translate import _
class crm_lead_forward_to_partner(osv.osv_memory):
"""Forwards lead history"""
@ -31,20 +33,27 @@ class crm_lead_forward_to_partner(osv.osv_memory):
_columns = {
'name': fields.selection([('user', 'User'), ('partner', 'Partner'), \
('email', 'Email Address')], 'Send to', required=True),
'user_id': fields.many2one('res.users', "User"),
'partner_id' : fields.many2one('res.partner', 'Partner'),
'address_id' : fields.many2one('res.partner.address', 'Address'),
'email_from' : fields.char('From', required=True, size=128),
'email_to' : fields.char('To', required=True, size=128),
'subject' : fields.char('Subject', required=True, size=128),
'message' : fields.text('Message', required=True),
('email', 'Email Address')], 'Send to', required=True),
'user_id': fields.many2one('res.users', "User"),
'partner_id' : fields.many2one('res.partner', 'Partner'),
'address_id' : fields.many2one('res.partner.address', 'Address'),
'email_from' : fields.char('From', required=True, size=128),
'email_to' : fields.char('To', required=True, size=128),
'subject' : fields.char('Subject', required=True, size=128),
'message' : fields.text('Message', required=True),
'history': fields.selection([('latest', 'Latest email'), ('whole', 'Whole Story'), ('info', 'Case Information')], 'Send history', required=True),
'add_cc': fields.boolean('Add as CC', required=False, help="Selcect if you want this user to add as cc for this case.This user will receive all future conversations"),
'add_cc': fields.boolean('Add as CC', required=False, help="Check this box if you want this address to be added in the CC list"\
" for this case, in order to receive all future conversations"),
}
_defaults = {
'history': 'latest',
'add_cc': True,
'email_from': lambda self, cr, uid, *a: self.pool.get('res.users')._get_email_from(cr, uid, uid)[uid]
}
def get_whole_history(self, cr, uid, ids, context=None):
"""This function gets whole communication history and returns as top posting style
"""This function gets whole communication history and returns as top posting style
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@ -87,13 +96,10 @@ class crm_lead_forward_to_partner(osv.osv_memory):
"""
if not user:
return {'value': {'email_to': False}}
email = False
addr = self.pool.get('res.users').read(cr, uid, user, ['address_id'])['address_id']
if addr:
email = self.pool.get('res.partner.address').read(cr, uid, addr[0] , ['email'])['email']
email = self.pool.get('res.users')._get_email_from(cr, uid, [user])[user]
return {'value': {'email_to': email}}
def on_change_history(self, cr, uid, ids, history, context=None):
def on_change_history(self, cr, uid, ids, history_type, context=None):
"""Gives message body according to type of history selected
* info: Forward the case information
* whole: Send the whole history
@ -106,31 +112,35 @@ class crm_lead_forward_to_partner(osv.osv_memory):
"""
#TODO: ids and context are not comming
res = False
msg_val = ''
res_id = context.get('active_id')
model = context.get('active_model')
model_pool = self.pool.get(model)
if not res_id or not model:
return res
if history == 'info':
msg_val = self._get_case_history(cr, uid, history_type, res_id, context=context)
if msg_val:
res = {'value': {'message' : '\n\n' + msg_val}}
return res
def _get_case_history(self, cr, uid, history_type, res_id, context=None):
if not res_id:
return
model_pool = self.pool.get('crm.lead')
if history_type == 'info':
msg_val = self.get_lead_details(cr, uid, res_id, context=context)
if history == 'whole':
elif history_type == 'whole':
log_ids = model_pool.browse(cr, uid, res_id, context=context).message_ids
log_ids = map(lambda x: x.id, log_ids)
log_ids = [x.id for x in log_ids]
if not log_ids:
raise osv.except_osv('Warning!', 'There is no history to send')
msg_val = self.get_whole_history(cr, uid, log_ids, context=context)
if history == 'latest':
elif history_type == 'latest':
log_ids = model_pool.browse(cr, uid, res_id, context=context).message_ids
if not log_ids:
raise osv.except_osv('Warning!', 'There is no history to send')
msg_val = self.get_latest_history(cr, uid, log_ids[0].id, context=context)
if msg_val:
res = {'value': {'message' : '\n\n' + msg_val}}
return res
return msg_val
def on_change_partner(self, cr, uid, ids, partner_id):
"""This function fills address information based on partner/user selected
@ -169,7 +179,7 @@ class crm_lead_forward_to_partner(osv.osv_memory):
context = {}
res_id = context.get('active_id', False)
model = context.get('active_model', False)
if not res_id or not model:
return {}
@ -184,19 +194,35 @@ class crm_lead_forward_to_partner(osv.osv_memory):
body = case_pool.format_body(this.message)
email_from = this.email_from or False
flag = False
flag = tools.email_send(
email_from,
emails,
this.subject,
body,
# extract attachements from case and emails according to mode
attachments = []
attach_pool = self.pool.get('ir.attachment')
direct_attachments = attach_pool.search(cr, uid, [('res_model', '=', 'crm.lead'), ('res_id', '=', res_id)], context=context)
attachments += attach_pool.browse(cr, uid, direct_attachments, context=context)
if this.history in ['latest', 'whole'] and case.message_ids:
msgs = case.message_ids
if this.history == 'latest':
msgs = msgs[:1]
attachments.extend(itertools.chain(*[m.attachment_ids for m in msgs]))
result = tools.email_send(
email_from,
emails,
this.subject,
body,
openobject_id=str(case.id),
attach=[(a.datas_fname or a.name, base64.decodestring(a.datas)) for a in attachments if a.datas],
reply_to=case.section_id.reply_to,
)
if flag:
if result:
case_pool._history(cr, uid, [case], _('Forward'), history=True, email=this.email_to, subject=this.subject, details=body, email_from=email_from)
if not flag:
raise osv.except_osv(_('Error!'), _('Unable to send mail. Please check SMTP is configured properly.'))
if this.add_cc:
else:
raise osv.except_osv(_('Error!'), _('Unable to send mail. Please check SMTP is configured properly.'))
if this.add_cc and (not case.email_cc or not this.email_to in case.email_cc):
case_pool.write(cr, uid, case.id, {'email_cc' : case.email_cc and case.email_cc + ', ' + this.email_to or this.email_to})
return {}
def get_lead_details(self, cr, uid, lead_id, context=None):
@ -209,11 +235,11 @@ class crm_lead_forward_to_partner(osv.osv_memory):
'zip', 'city', 'country_id', 'state_id', 'email_from',
'phone', 'fax', 'mobile'
]
for field_name in field_names:
field_definition = lead_proxy._columns[field_name]
value = None
if field_definition._type == 'selection':
if hasattr(field_definition.selection, '__call__'):
key = field_definition.selection(lead_proxy, cr, uid, context=context)
@ -225,7 +251,7 @@ class crm_lead_forward_to_partner(osv.osv_memory):
value = lead[field_name].name_get()[0][1]
else:
value = lead[field_name]
message.append("%s: %s" % (field_definition.string, value or ''))
elif lead.type == 'opportunity':
pa = lead.partner_address_id
@ -254,29 +280,21 @@ class crm_lead_forward_to_partner(osv.osv_memory):
if context is None:
context = {}
defaults = super(crm_lead_forward_to_partner, self).default_get(cr, uid, fields, context=context)
active_ids = context.get('active_ids')
if not active_ids:
return {}
return defaults
lead_proxy = self.pool.get('crm.lead')
lead = lead_proxy.browse(cr, uid, active_ids[0], context=context)
message = False
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
email_from = ''
if user.address_id and user.address_id.email:
email_from = "%s <%s>" % (user.name, user.address_id.email)
message = self.get_lead_details(cr, uid, lead.id, context=context)
res = {
'email_from' : email_from,
'subject' : '%s: ' % (_('Fwd'), lead.name),
message = self._get_case_history(cr, uid, defaults.get('history'), lead.id, context=context)
defaults.update({
'subject' : '%s: %s' % (_('Fwd'), lead.name),
'message' : message,
}
if 'history' in fields:
res.update({'history': 'latest'})
return res
})
return defaults
crm_lead_forward_to_partner()

View File

@ -7,28 +7,24 @@
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Forward to Partner">
<separator string="User" colspan="4" />
<separator string="Sender" colspan="4" />
<field name="email_from" colspan="2" />
<field name="history" colspan="2" on_change="on_change_history(history, context)"/>
<separator string="Send to" colspan="4" />
<separator string="Recipient" colspan="4" />
<field name="name" colspan="2" />
<group col="2" colspan="2" attrs="{ 'invisible' : [('name','!=','user')]}">
<group col="2" colspan="2" attrs="{ 'invisible' : [('name','!=','user')]}">
<field name="user_id"
attrs="{ 'required' : [('name','=','user')]}"
on_change="on_change_email(user_id)" />
</group>
<group col="4" colspan="4" attrs="{'invisible' : [('name','!=','partner')]}">
<field name="partner_id" attrs="{'required' : [('name','=','partner')]}" on_change="on_change_partner(partner_id)" colspan="2" />
<field name="address_id" string="Contact" on_change="on_change_address(address_id)" colspan="2" />
</group>
<field colspan="4" name="email_to" attrs="{ 'required' : [('name','=','email')]}" />
<newline/>
<group colspan="2" col="2">
<field name="add_cc" colspan="2"/>
</group>
<separator string="Email" colspan="4" />
<field name="partner_id" attrs="{'required' : [('name','=','partner')]}" on_change="on_change_partner(partner_id)" colspan="2" />
<field name="address_id" string="Contact" on_change="on_change_address(address_id)" colspan="2" />
</group>
<field colspan="2" name="email_to" attrs="{ 'required' : [('name','=','email')]}" />
<field name="add_cc"/>
<separator string="Message" colspan="4" />
<field name="subject" colspan="4" />
<separator string="Mesage body" colspan="4" />
<field name="message" colspan="4" nolabel="1"/>
<separator string="" colspan="4" />
<group colspan="4" col="2">

View File

@ -53,7 +53,8 @@ class crm_send_new_email(osv.osv_memory):
_columns = {
'email_to' : fields.char('To', size=64, required=True),
'email_from' : fields.char('From', size=64, required=True),
'email_cc' : fields.char('CC', size=128),
'email_cc' : fields.char('CC', size=128, help="Carbon Copy: list of recipients that will receive"\
" a copy of this mail, and future communication related to this case"),
'subject': fields.char('Subject', size=128, required=True),
'text': fields.text('Message', required=True),
'state': fields.selection(crm.AVAILABLE_STATES, string='Set New State To', required=True),
@ -92,7 +93,7 @@ class crm_send_new_email(osv.osv_memory):
case = case_pool.browse(cr, uid, res_id)
if context.get('mail', 'new') == 'new':
if len(case.message_ids):
if case.message_ids:
message_id = case.message_ids[0].message_id
else:
hist = hist_obj.browse(cr, uid, res_id)
@ -112,8 +113,6 @@ class crm_send_new_email(osv.osv_memory):
if message_id:
x_headers['References'] = "%s" % (message_id)
flag = False
flag = tools.email_send(
email_from,
emails,
@ -121,10 +120,11 @@ class crm_send_new_email(osv.osv_memory):
body,
email_cc=email_cc,
attach=attach,
reply_to=case.section_id and case.section_id.reply_to or email_from,
reply_to=case.section_id and case.section_id.reply_to,
openobject_id=str(case.id),
x_headers=x_headers
)
if not flag:
raise osv.except_osv(_('Error!'), _('Unable to send mail. Please check SMTP is configured properly.'))
if flag:
@ -165,23 +165,23 @@ class crm_send_new_email(osv.osv_memory):
mod_obj = self.pool.get(model)
res_id = context and context.get('active_ids', []) or []
user_obj = self.pool.get('res.users')
user_mail_from = user_obj._get_email_from(cr, uid, [uid], context=context)[uid]
for case in mod_obj.browse(cr, uid, res_id):
if 'email_to' in fields:
res.update({'email_to': case.email_from})
if 'email_from' in fields:
res.update({'email_from': (case.section_id and case.section_id.reply_to) or \
(case.user_id and case.user_id.address_id and \
case.user_id.address_id.email and \
"%s <%s>" % (case.user_id.name, case.user_id.address_id.email)) or \
tools.config.get('email_from',False)})
res.update({'email_from': case.section_id and case.section_id.reply_to or user_mail_from})
if 'subject' in fields:
res.update({'subject': '[%s] %s' % (str(case.id), context.get('subject', case.name) or '')})
res.update({'subject': str(context.get('subject', case.name) or '')})
if 'email_cc' in fields:
res.update({'email_cc': case.email_cc or ''})
if 'text' in fields:
res.update({'text': '\n\n'+(case.user_id.signature or '')})
if 'state' in fields:
res.update({'state': 'pending'})
return res
def get_reply_defaults(self, cr, uid, fields, context=None):
@ -191,6 +191,9 @@ class crm_send_new_email(osv.osv_memory):
hist_obj = self.pool.get('mailgate.message')
res_ids = context and context.get('active_ids', []) or []
user_obj = self.pool.get('res.users')
user_mail_from = user_obj._get_email_from(cr, uid, [uid], context=context)[uid]
include_original = context and context.get('include_original', False) or False
res = {}
for hist in hist_obj.browse(cr, uid, res_ids, context=context):
@ -201,14 +204,12 @@ class crm_send_new_email(osv.osv_memory):
return {}
model_pool = self.pool.get(model)
res_id = hist.res_id
res_id = hist.res_id
case = model_pool.browse(cr, uid, res_id)
if 'email_to' in fields:
res.update({'email_to': case.email_from or hist.email_from or False})
if 'email_from' in fields:
res.update({'email_from': (case.section_id and case.section_id.reply_to) or \
(case.user_id and case.user_id.address_id and \
case.user_id.address_id.email) or hist.email_to or tools.config.get('email_from',False)})
res.update({'email_from': case.section_id and case.section_id.reply_to or user_mail_from})
signature = '\n' + (case.user_id.signature or '')
original = [signature]
@ -251,13 +252,6 @@ class crm_send_new_email(osv.osv_memory):
return True
if tools.config.get('email_from'):
return True
for case in mod_obj.browse(cr, uid, context.get('active_ids', [])):
if not case.user_id:
raise osv.except_osv(_('Error'), _('You must define a responsible user for this case in order to use this action!'))
if not case.user_id.address_id.email:
raise osv.except_osv(_('Warning!'), _("Please specify user's email address !"))
return True
crm_send_new_email()

View File

@ -10,12 +10,11 @@
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Send New Mail" col="4">
<separator string="Send New Mail" colspan="4"/>
<group colspan="4" col="6">
<field name="email_from" />
<field name="email_to" />
<field name="email_cc" />
<field name="subject" colspan="6"/>
<group colspan="4" col="2">
<field name="email_from"/>
<field name="email_to" />
<field name="email_cc"/>
<field name="subject"/>
</group>
<notebook colspan="6">
<page string="Message">

View File

@ -152,7 +152,7 @@ class mailgate_tool(osv.osv_memory):
_name = 'email.server.tools'
_description = "Email Server Tools"
def _to_decode(self, s, charsets):
if not s:
return s
@ -168,7 +168,7 @@ class mailgate_tool(osv.osv_memory):
if text:
text = decode_header(text.replace('\r', ''))
return ''.join(map(lambda x:self._to_decode(x[0], [x[1]]), text or []))
def to_email(self, text):
_email = re.compile(r'.*<.*@.*\..*>', re.UNICODE)
def record(path):
@ -179,7 +179,7 @@ class mailgate_tool(osv.osv_memory):
bits = _email.sub(record, text)
return bits
def history(self, cr, uid, model, res_ids, msg, attach, context=None):
"""This function creates history for mails fetched
@param self: The object pointer
@ -212,7 +212,7 @@ class mailgate_tool(osv.osv_memory):
}
msg_id = msg_pool.create(cr, uid, msg_data, context=context)
return True
def email_send(self, cr, uid, model, res_id, msg, from_email=False, email_default=False):
"""This function Sends return email on submission of Fetched email in OpenERP database
@param self: The object pointer
@ -227,10 +227,7 @@ class mailgate_tool(osv.osv_memory):
model_pool = self.pool.get(model)
from_email = from_email or tools.config.get('email_from', None)
message = email.message_from_string(tools.ustr(msg).encode('utf-8'))
subject = "[%s] %s" %(res_id, message['Subject'])
#msg_mails = []
#mails = [self._decode_header(message['From']), self._decode_header(message['To'])]
#mails += self._decode_header(message.get('Cc', '')).split(',')
subject = message['Subject']
values = {}
if hasattr(model_pool, 'emails_get'):
@ -241,11 +238,6 @@ class mailgate_tool(osv.osv_memory):
em = emails['user_email'] + emails['email_from'] + emails['email_cc']
msg_mails = map(self.to_email, filter(None, em))
#mm = [self._decode_header(message['From']), self._decode_header(message['To'])]
#mm += self._decode_header(message.get('Cc', '')).split(',')
#msg_mails = map(self.to_email, filter(None, mm))
encoding = message.get_content_charset()
message['body'] = message.get_payload(decode=True)
if encoding:
@ -258,10 +250,9 @@ Hello %s,""" % (from_mail))
Your Request ID: %s""") % (res_id)
body += _("""
Thanks
-------- Original Message --------
-------- Original Message --------
%s
""") % (self._to_decode(message['body'], [encoding]))
res = None
@ -284,7 +275,6 @@ Thanks
@param message: Email details
@param attach: Email attachments
@param context: A standard dictionary for contextual values"""
model_pool = self.pool.get(model)
if not context:
context = {}
@ -441,14 +431,14 @@ Thanks
# Store messages
context.update({'model' : model})
if hasattr(model_pool, '_history'):
model_pool._history(cr, uid, res_ids, _('Receive'), history=True,
subject = msg.get('subject'),
email = msg.get('to'),
details = msg.get('body'),
email_from = msg.get('from'),
message_id = msg.get('message-id'),
model_pool._history(cr, uid, res_ids, _('Receive'), history=True,
subject = msg.get('subject'),
email = msg.get('to'),
details = msg.get('body'),
email_from = msg.get('from'),
message_id = msg.get('message-id'),
references = msg.get('references', False),
attach = msg.get('attachments', {}).items(),
attach = msg.get('attachments', {}).items(),
context = context)
else:
self.history(cr, uid, model, res_ids, msg, att_ids, context=context)
@ -476,5 +466,3 @@ Thanks
return res
mailgate_tool()