'section_id': case.section_id.id
}
obj = self.pool.get('crm.case.log')
- if history and case.description:
+ if history:
obj = self.pool.get('crm.case.history')
data['description'] = details or case.description
- data['email'] = email or \
+ data['email_to'] = email or \
++ (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 False
++ case.user_id.address_id.email) or tools.config.get('email_from',False)
+ data['email_from'] = email_from or \
++ (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 False
++ case.user_id.address_id.email) or tools.config.get('email_from',False)
res = obj.create(cr, uid, data, context)
return True
_history = __history
if case.section_id.reply_to and case.email_from:
src = case.email_from
dest = case.section_id.reply_to
- body = case.email_last or case.description
+ body = ""
- body = case.email_last or case.description
++ body = case.email_last or case.description
if not destination:
src, dest = dest, src
- if case.user_id.signature:
- body += '\n\n%s' % (case.user_id.signature or '')
+ if body and case.user_id.signature:
- body += '\n\n%s' % (case.user_id.signature).encode('utf8')
++ body += '\n\n%s' % (case.user_id.signature)
++
++ body = self.format_body(body)
dest = [dest]
attach_to_send = None
src,
dest,
"Reminder: [%s] %s" % (str(case.id), case.name, ),
-- self.format_body(body),
++ body,
reply_to=case.section_id.reply_to,
openobject_id=str(case.id),
attach=attach_to_send
)
- if flag:
- raise osv.except_osv(_('Email!'),("Email Successfully Sent"))
- else:
- raise osv.except_osv(_('Email Fail!'),("Email is not sent successfully"))
++ self._history(cr, uid, [case], _('Send'), history=True, email=dest, details=body, email_from=src)
+ #if flag:
+ # raise osv.except_osv(_('Email!'),("Email Successfully Sent"))
+ #else:
+ # raise osv.except_osv(_('Email Fail!'),("Email is not sent successfully"))
return True
def _check(self, cr, uid, ids=False, context={}):
class base_action_rule(osv.osv):
_inherit = 'base.action.rule'
_description = 'Action Rules'
+
+ def email_send(self, cr, uid, obj, emails, body, emailfrom=tools.config.get('email_from',False), context={}):
+ body = self.format_mail(obj, body)
+ if not emailfrom:
+ if hasattr(obj, 'user_id') and obj.user_id and obj.user_id.address_id and obj.user_id.address_id.email:
+ emailfrom = obj.user_id.address_id.email
+
+ name = '[%d] %s' % (obj.id, tools.ustr(obj.name))
+ emailfrom = tools.ustr(emailfrom)
- if obj.section_id and obj.section_id.reply_to:
++ if hasattr(obj, 'section_id') and obj.section_id and obj.section_id.reply_to:
+ reply_to = obj.section_id.reply_to
+ else:
+ reply_to = emailfrom
+ if not emailfrom:
+ raise osv.except_osv(_('Error!'),
+ _("No E-Mail ID Found for your Company address!"))
+ return tools.email_send(emailfrom, emails, name, body, reply_to=reply_to, openobject_id=str(obj.id))
def do_check(self, cr, uid, action, obj, context={}):
ok = super(base_action_rule, self).do_check(cr, uid, action, obj, context=context)
res = super(base_action_rule, self).do_action(cr, uid, action, model_obj, obj, context=context)
write = {}
-- if action.act_section_id:
++ if hasattr(action, act_section_id) and action.act_section_id:
obj.section_id = action.act_section_id
write['section_id'] = action.act_section_id.id
class crm_cases(osv.osv):
_name = "crm.case"
-- _inherit = "crm.case"
-
- def _decode_header(self, s):
- from email.Header import decode_header
- s = decode_header(s)
- return ''.join(map(lambda x:x[0].decode(x[1] or 'ascii', 'replace'), s))
++ _inherit = "crm.case"
def msg_new(self, cr, uid, msg):
mailgate_obj = self.pool.get('mail.gateway')
msg_body = mailgate_obj.msg_body_get(msg)
++ msg_subject = mailgate_obj._decode_header(msg['Subject'])
++ msg_from = mailgate_obj._decode_header(msg['From'])
++ msg_cc = mailgate_obj._decode_header(msg['Cc'])
++ body = self.format_body(msg_body['body'])
data = {
- 'name': msg['Subject'],
- 'email_from': msg['From'],
- 'email_cc': msg['Cc'],
- 'name': self._decode_header(msg['Subject']),
- 'email_from': self._decode_header(msg['From']),
- 'email_cc': msg['Cc'] and self._decode_header(msg['Cc']),
++ 'name': msg_subject,
++ 'email_from': msg_from,
++ 'email_cc': msg_cc,
'user_id': False,
-- 'description': msg_body['body'],
++ 'description': body,
}
-- res = mailgate_obj.partner_get(cr, uid, msg['From'])
++ res = mailgate_obj.partner_get(cr, uid, msg_from)
if res:
data.update(res)
res = self.create(cr, uid, data)
cases = self.browse(cr, uid, [res])
- self._history(cr, uid, cases, _('Receive'), history=True, email=msg['From'])
- self._history(cr, uid, cases, _('Receive'), history=True, email=self._decode_header(msg['From']))
++ self._history(cr, uid, cases, _('Receive'), history=True, details=body, email_from=msg_from)
return res
def msg_update(self, cr, uid, ids, msg, data={}, default_act='pending'):
if 'partner' in msg_actions:
data['email_from'] = msg_actions['partner'][:128]
--
++ msg_from = self._decode_header(msg['From'])
res = self.write(cr, uid, select, data)
cases = self.browse(cr, uid, select)
-- self._history(cr, uid, cases, _('Receive'), history=True, email=msg['From'])
++ self._history(cr, uid, cases, _('Receive'), history=True, details=body_data, email_from=msg['From'])
getattr(self,act)(cr, uid, select)
return res
import time, socket
-email_re = re.compile(r"""
- ([a-zA-Z][\w\.-]*[a-zA-Z0-9] # username part
- @ # mandatory @ sign
- [a-zA-Z0-9][\w\.-]* # domain must start with a letter ... Ged> why do we include a 0-9 then?
- \.
- [a-z]{2,3} # TLD
- )
- """, re.VERBOSE)
+email_re = re.compile(r"([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6})")
case_re = re.compile(r"\[([0-9]+)\]", re.UNICODE)
command_re = re.compile("^Set-([a-z]+) *: *(.+)$", re.I + re.UNICODE)
--reference_re = re.compile("<.*-tinycrm-(\\d+)@(.*)>", re.UNICODE)
++reference_re = re.compile("<.*-openobject-(\\d+)@(.*)>", re.UNICODE)
priorities = {
'1': '1 (Highest)',
'partner_id': adr[0].get('partner_id', False) and adr[0]['partner_id'][0] or False
}
++ def _to_decode(self, s, charsets):
++ for charset in charsets:
++ if charset:
++ try:
++ return s.decode(charset)
++ except UnicodeError:
++ pass
++ try:
++ return s.decode('ascii')
++ except UnicodeError:
++ return s
++
def _decode_header(self, s):
from email.Header import decode_header
-- s = decode_header(s)
-- return ''.join(map(lambda x:x[0].decode(x[1] or 'ascii', 'replace'), s))
++ s = decode_header(s)
++ return ''.join(map(lambda x:self._to_decode(x[0], [x[1]]), s))
def msg_new(self, msg):
message = self.msg_body_get(msg)
++ msg_subject = self._decode_header(msg['Subject'])
++ msg_from = self._decode_header(msg['From'])
++ msg_cc = self._decode_header(msg['Cc'] or '')
++
data = {
-- 'name': self._decode_header(msg['Subject']),
-- 'email_from': self._decode_header(msg['From']),
- 'email_cc': self._decode_header(msg['Cc'] or ''),
- 'email_cc': self._decode_header(msg['Cc'] or ''),
- 'canal_id': self.canal_id,
++ 'name': msg_subject,
++ 'email_from': msg_from,
++ 'email_cc': msg_cc,
'user_id': False,
'description': message['body'],
}
- data.update(self.partner_get(self._decode_header(msg['From'])))
- try:
- data.update(self.partner_get(self._decode_header(msg['From'])))
- except Exception, e:
- import netsvc
- netsvc.Logger().notifyChannel('mailgate', netsvc.LOG_ERROR, "%s" % e)
++ data.update(self.partner_get(msg_from))
try:
id = self.rpc(self.model, 'create', data)
if part.get_content_maintype()=='text':
buf = part.get_payload(decode=True)
if buf:
-- txt = buf.decode(part.get_charsets()[0] or 'ascii', 'replace')
++ txt = self._to_decode(buf, part.get_charsets())
txt = re.sub("<(\w)>", replace, txt)
txt = re.sub("<\/(\w)>", replace, txt)
if txt and part.get_content_subtype() == 'plain':
--- /dev/null
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). All Rights Reserved
+# $Id$
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from osv import osv, fields
+from tools.translate import _
+import base64
+import tools
+from crm import crm
+
+class crm_send_new_email(osv.osv_memory):
+ """ Sends new email for the case"""
+ _name = "crm.send.mail"
+ _description = "Case Send new email"
+
+ _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),
+ 'subject': fields.char('Subject', size=128, required=True),
+ 'text': fields.text('Message', required=True),
+ 'state': fields.selection(crm.AVAILABLE_STATES, string='State'),
+ 'doc1': fields.binary("Attachment1"),
+ 'doc2': fields.binary("Attachment2"),
+ 'doc3': fields.binary("Attachment3"),
+ }
+
+ def action_cancel(self, cr, uid, ids, context=None):
+ """ Closes Phonecall to Opportunity form
+ """
+ return {'type':'ir.actions.act_window_close'}
+
+ def action_send(self, cr, uid, ids, context=None):
+ """ This sends an email to ALL the addresses of the selected partners.
+ """
+ if not context:
+ context = {}
+
+ if not context.get('model'):
+ raise osv.except_osv(_('Error'), _('Can not send mail!'))
+
+ model = context.get('model')
+ case_pool = self.pool.get(model)
+ res_id = context and context.get('active_id', False) or False
+
+ for data in self.read(cr, uid, ids, context=context):
+ attach = filter(lambda x: x, [data['doc1'], data['doc2'], data['doc3']])
+ attach = map(lambda x: x and ('Attachment'+str(attach.index(x)+1), base64.decodestring(x)), attach)
+
+ if context.get('mail', 'new') == 'new':
+ case = case_pool.browse(cr, uid, res_id)
+ else:
+ hist_obj = self.pool.get('crm.case.history')
+ hist = hist_obj.browse(cr, uid, res_id)
+ model = hist.log_id.model_id.model
+ model_pool = self.pool.get(model)
+ case = model_pool.browse(cr, uid, hist.log_id.res_id)
+ emails = [data['email_to']] + (data['email_cc'] or '').split(',')
+ emails = filter(None, emails)
+ body = data['text']
+
+ if case.user_id.signature:
+ body += '\n\n%s' % (case.user_id.signature)
-
- case_pool._history(cr, uid, [case], _('Send'), history=True, email=data['email_to'], details=body)
++ body = case_pool.format_body(body)
+ email_from = data.get('email_from', False)
++ case_pool._history(cr, uid, [case], _('Send'), history=True, email=data['email_to'], details=body, email_from=email_from)
++
+ flag = tools.email_send(
+ email_from,
+ emails,
+ data['subject'],
- case_pool.format_body(body),
++ body,
+ attach=attach,
+ reply_to=case.section_id.reply_to,
+ openobject_id=str(case.id),
+ )
+ if flag:
+ if data['state'] == 'unchanged':
+ pass
+ elif data['state'] == 'done':
+ case_pool.case_close(cr, uid, [case.id])
+ elif data['state'] == 'draft':
+ case_pool.case_reset(cr, uid, [case.id])
+ elif data['state'] in ['cancel', 'open', 'pending']:
+ act = 'case_' + data['state']
+ getattr(case_pool, act)(cr, uid, [case.id])
+ cr.commit()
+
+# Commented because form does not close due to raise
+# raise osv.except_osv(_('Email!'), ("Email Successfully Sent"))
+# else:
+# raise osv.except_osv(_('Warning!'), _("Email not sent !"))
++
+ return {}
+
+ def default_get(self, cr, uid, fields, context=None):
+ """
+ This function gets default values
+ """
+ if not context:
+ context = {}
+
+ if not context.get('model'):
+ raise osv.except_osv(_('Error'), _('Can not send mail!'))
+
+ res = super(crm_send_new_email, self).default_get(cr, uid, fields, context=context)
+
+ if context.get('mail') == 'reply':
+ res.update(self.get_reply_defaults(cr, uid, fields, context=context))
+ return res
+
+ model = context.get('model')
+ mod_obj = self.pool.get(model)
+ res_id = context and context.get('active_ids', []) or []
+
+ 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.user_id and case.user_id.address_id and 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 \
++ (case.user_id and case.user_id.address_id and \
++ case.user_id.address_id.email) or tools.config.get('email_from',False)})
+ if 'subject' in fields:
+ res.update({'subject': '[%s] %s' %(str(case.id), case.name or '')})
+ if 'email_cc' in fields:
+ res.update({'email_cc': case.email_cc or ''})
+ if 'text' in fields:
+ res.update({'text': case.description or ''})
+ if 'state' in fields:
+ res.update({'state': 'pending'})
+ return res
+
+ def get_reply_defaults(self, cr, uid, fields, context=None):
+ """
+ This function gets default values for reply mail
+ """
+ hist_obj = self.pool.get('crm.case.history')
+ res_ids = context and context.get('active_ids', []) or []
+ res = {}
+ for hist in hist_obj.browse(cr, uid, res_ids):
+ model = hist.log_id.model_id.model
+ model_pool = self.pool.get(model)
+ case = model_pool.browse(cr, uid, hist.log_id.res_id)
+ if 'email_to' in fields:
- res['email_to']=case.email_from or hist.email_from or ''
++ res.update({'email_to': case.email_from or hist.email_from or False})
+ if 'email_from' in fields:
- res['email_from']=(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','')
++ 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)})
+ if 'text' in fields:
- header = '\n\n-------- Original Message --------'
- sender = 'From: %s' % (hist.email_from or '')
++ header = '-------- Original Message --------'
++ sender = 'From: %s' %(hist.email_from or '')
+ to = 'To: %s' % (hist.email_to or '')
+ sentdate = 'Date: %s' % (hist.date)
+ desc = '\n%s'%(hist.description)
+ original = [header, sender, to, sentdate, desc]
+ original = '\n'.join(original)
+ res['text']=original
+ if 'subject' in fields:
+ res.update({'subject': '[%s] %s' %(str(case.id), case.name or '')})
+ if 'state' in fields:
+ res['state']='pending'
+ return res
+
+ def view_init(self, cr, uid, fields_list, context=None):
+ """
+ This function checks for precondition before wizard executes
+ @param self: The object pointer
+ @param cr: the current row, from the database cursor,
+ @param uid: the current user’s ID for security checks,
+ @param fields: List of fields for default value
+ @param context: A standard dictionary for contextual values
+
+ """
+ if not context:
+ context = {}
+
+ if not context.get('model'):
+ raise osv.except_osv(_('Error'), _('Can not send mail!'))
+ model = context.get('model')
+ mod_obj = self.pool.get(model)
+ if context.get('mail') == 'reply':
+ 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()
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
}
return res
-- def _decode_header(self, s):
++ def _to_decode(self, s, charsets):
++ for charset in charsets:
++ if charset:
++ try:
++ return s.decode(charset)
++ except UnicodeError:
++ pass
++ try:
++ return s.decode('ascii')
++ except UnicodeError:
++ return s
++
++ def _decode_header(self, s):
from email.Header import decode_header
s = decode_header(s)
-- return ''.join(map(lambda x:x[0].decode(x[1] or 'ascii', 'replace'), s))
++ return ''.join(map(lambda x:self._to_decode(x[0], x[1]), s))
def msg_new(self, cr, uid, msg, model):
message = self.msg_body_get(msg)
if part.get_content_maintype()=='text':
buf = part.get_payload(decode=True)
if buf:
-- txt = buf.decode(part.get_charsets()[0] or 'ascii', 'replace')
++ txt = self._to_decode(buf, part.get_charsets)
txt = re.sub("<(\w)>", replace, txt)
txt = re.sub("<\/(\w)>", replace, txt)
if txt and part.get_content_subtype() == 'plain':