You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
549 lines
25 KiB
549 lines
25 KiB
# -*- coding: utf-8 -*-
|
|
###################################################################################
|
|
#
|
|
# Cybrosys Technologies Pvt. Ltd.
|
|
#
|
|
# Copyright (C) 2019-TODAY Cybrosys Technologies (<https://www.cybrosys.com>).
|
|
# Author: Noushid Khan.P (<https://www.cybrosys.com>)
|
|
#
|
|
# This program is free software: you can modify
|
|
# it under the terms of the GNU Affero General Public License (AGPL) 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 Affero General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
#
|
|
###################################################################################
|
|
|
|
import json
|
|
|
|
from odoo import models, fields, api, _
|
|
from odoo.exceptions import UserError
|
|
import http.client
|
|
|
|
|
|
class SendGridEmail(models.Model):
|
|
_inherit = 'mailing.mailing'
|
|
|
|
email_temp = fields.Many2one("email.template", string="Email Template")
|
|
temp_id = fields.Char(string="Template ID")
|
|
from_email = fields.Many2one("email.sent", string="Sender Email")
|
|
to_email_partner = fields.Many2many("res.partner", string="Recipient Emails")
|
|
to_email_partner_check = fields.Boolean()
|
|
to_email_lead = fields.Many2many("crm.lead", string="Recipient Emails")
|
|
to_email_lead_check = fields.Boolean()
|
|
to_email_contact = fields.Many2many("mailing.contact", string="Recipient Emails")
|
|
to_email_contact_check = fields.Boolean()
|
|
to_email_applicant = fields.Many2many("hr.applicant", string="Recipient Emails")
|
|
to_email_applicant_check = fields.Boolean()
|
|
email_finder = fields.Integer(string="Email finder")
|
|
sent_count = fields.Integer(string="Send Count")
|
|
send_grid_check = fields.Boolean()
|
|
temp_check = fields.Boolean()
|
|
|
|
def action_send_grid(self):
|
|
"""
|
|
function used for Sending emails using
|
|
SendGrid API using "sendgrid" Button
|
|
and creating report based on states.
|
|
|
|
"""
|
|
company_id = self.env.company
|
|
api_key = ""
|
|
conn = http.client.HTTPSConnection("api.sendgrid.com")
|
|
if not self.temp_id:
|
|
raise UserError(_("It Needs A Template ID"))
|
|
if self.from_email:
|
|
from_email = self.from_email.email_id
|
|
from_name = self.from_email.name
|
|
else:
|
|
from_email = "noreply@johndoe.com"
|
|
from_name = "JohnDoe"
|
|
if self.to_email_partner:
|
|
api_info = self.env['ir.config_parameter'].search(
|
|
[('key', '=', "SendGrid API Key " + company_id.name + "")])
|
|
if not api_info:
|
|
raise UserError(_("It Needs API Key"))
|
|
if api_info.company_id.id == self.env.company.id:
|
|
api_key = api_info.value
|
|
if not api_key and api_key == "":
|
|
raise UserError(_("Your Company Needs an API Key"))
|
|
for data in self.to_email_partner:
|
|
to_email = data.email
|
|
to_name = data.name
|
|
to_company = data.company_name
|
|
if not to_company:
|
|
to_company = ""
|
|
temp_id = self.temp_id
|
|
if to_email:
|
|
payload = "{\"personalizations\":[{\"to\":[{\"email\":\"" + to_email + "\"}],\"dynamic_template_data\":{\"firstname\":\"" + to_name + "\",\"english\":\"true\",\"company\":\"" + to_company + "\"},\"subject\":\"Official Mail\"}],\"from\":{\"email\":\"" + from_email + "\",\"name\":\"" + from_name + "\"},\"template_id\":\"" + temp_id + "\"}"
|
|
|
|
headers = {
|
|
'authorization': "Bearer " + api_key + "",
|
|
'content-type': "application/json"
|
|
}
|
|
|
|
conn.request("POST", "/v3/mail/send", payload, headers)
|
|
|
|
res = conn.getresponse()
|
|
data_msg = res.read()
|
|
error_msg = ''
|
|
if data_msg.decode("utf-8"):
|
|
error_data = json.loads(data_msg.decode("utf-8"))
|
|
error_msg = error_data['errors'][0]['message']
|
|
if not data_msg.decode("utf-8"):
|
|
self.sent_count += 1
|
|
self.write({
|
|
'state': 'done'
|
|
})
|
|
self.env['email.api'].create({
|
|
'name': self.subject,
|
|
'to_email_partner': data.id,
|
|
'to_email': to_email,
|
|
'recipient_name': to_name,
|
|
'company_name': to_company,
|
|
'from_email': self.from_email.id,
|
|
'temp_type': self.email_temp.id,
|
|
'temp_id': self.temp_id,
|
|
'to_email_partner_check': True,
|
|
'email_finder': self.id
|
|
})
|
|
|
|
elif error_msg:
|
|
self.env['email.api'].create({
|
|
'name': self.subject,
|
|
'to_email_partner': data.id,
|
|
'to_email': to_email,
|
|
'recipient_name': to_name,
|
|
'company_name': to_company,
|
|
'from_email': self.from_email.id,
|
|
'temp_type': self.email_temp.id,
|
|
'temp_id': self.temp_id,
|
|
'error_msg': error_msg,
|
|
'state': 'error',
|
|
'to_email_partner_check': True,
|
|
'error_check': True,
|
|
'email_finder': self.id
|
|
})
|
|
self.email_finder = self.id
|
|
self.send_grid_check = True
|
|
elif self.to_email_lead:
|
|
api_info = self.env['ir.config_parameter'].search(
|
|
[('key', '=', "SendGrid API Key " + company_id.name + "")])
|
|
if not api_info:
|
|
raise UserError(_("It Needs API Key"))
|
|
if api_info.company_id.id == self.env.company.id:
|
|
api_key = api_info.value
|
|
if not api_key and api_key == "":
|
|
raise UserError(_("Your Company Needs an API Key"))
|
|
for data in self.to_email_lead:
|
|
to_email = data.email_from
|
|
to_name = data.contact_name
|
|
if not to_name:
|
|
raise UserError(_("Your Lead Needs A Contact Name"))
|
|
to_company = data.partner_name
|
|
if not to_company:
|
|
to_company = ""
|
|
temp_id = self.temp_id
|
|
payload = ""
|
|
if to_email:
|
|
payload = "{\"personalizations\":[{\"to\":[{\"email\":\"" + to_email + "\"}],\"dynamic_template_data\":{\"firstname\":\"" + to_name + "\",\"english\":\"true\",\"company\":\"" + to_company + "\"},\"subject\":\"Official Mail\"}],\"from\":{\"email\":\"" + from_email + "\",\"name\":\"" + from_name + "\"},\"template_id\":\"" + temp_id + "\"}"
|
|
|
|
headers = {
|
|
'authorization': "Bearer " + api_key + "",
|
|
'content-type': "application/json"
|
|
}
|
|
|
|
conn.request("POST", "/v3/mail/send", payload, headers)
|
|
|
|
res = conn.getresponse()
|
|
data_msg = res.read()
|
|
|
|
error_msg = ''
|
|
if data_msg.decode("utf-8"):
|
|
error_data = json.loads(data_msg.decode("utf-8"))
|
|
error_msg = error_data['errors'][0]['message']
|
|
if not data_msg.decode("utf-8"):
|
|
self.sent_count += 1
|
|
self.write({
|
|
'state': 'done'
|
|
})
|
|
self.env['email.api'].create({
|
|
'name': self.subject,
|
|
'to_email_lead': data.id,
|
|
'to_email': to_email,
|
|
'recipient_name': to_name,
|
|
'company_name': to_company,
|
|
'from_email': self.from_email.id,
|
|
'temp_type': self.email_temp.id,
|
|
'temp_id': self.temp_id,
|
|
'to_email_lead_check': True,
|
|
'email_finder': self.id
|
|
})
|
|
|
|
elif error_msg:
|
|
self.env['email.api'].create({
|
|
'name': self.subject,
|
|
'to_email_lead': data.id,
|
|
'to_email': to_email,
|
|
'recipient_name': to_name,
|
|
'company_name': to_company,
|
|
'from_email': self.from_email.id,
|
|
'temp_type': self.email_temp.id,
|
|
'temp_id': self.temp_id,
|
|
'error_msg': error_msg,
|
|
'state': 'error',
|
|
'to_email_lead_check': True,
|
|
'error_check': True,
|
|
'email_finder': self.id
|
|
})
|
|
self.email_finder = self.id
|
|
self.send_grid_check = True
|
|
elif self.to_email_contact:
|
|
api_info = self.env['ir.config_parameter'].search(
|
|
[('key', '=', "SendGrid API Key " + company_id.name + "")])
|
|
if not api_info:
|
|
raise UserError(_("It Needs API Key"))
|
|
if api_info.company_id.id == self.env.company.id:
|
|
api_key = api_info.value
|
|
if not api_key and api_key == "":
|
|
raise UserError(_("Your Company Needs an API Key"))
|
|
for data in self.to_email_contact:
|
|
to_email = data.email
|
|
to_name = data.name
|
|
to_company = data.company_name
|
|
if not to_company:
|
|
to_company = ""
|
|
temp_id = self.temp_id
|
|
payload = ""
|
|
if to_email:
|
|
payload = "{\"personalizations\":[{\"to\":[{\"email\":\"" + to_email + "\"}],\"dynamic_template_data\":{\"firstname\":\"" + to_name + "\",\"english\":\"true\",\"company\":\"" + to_company + "\"},\"subject\":\"Official Mail\"}],\"from\":{\"email\":\"" + from_email + "\",\"name\":\"" + from_name + "\"},\"template_id\":\"" + temp_id + "\"}"
|
|
|
|
headers = {
|
|
'authorization': "Bearer " + api_key + "",
|
|
'content-type': "application/json"
|
|
}
|
|
|
|
conn.request("POST", "/v3/mail/send", payload, headers)
|
|
|
|
res = conn.getresponse()
|
|
data_msg = res.read()
|
|
|
|
error_msg = ''
|
|
if data_msg.decode("utf-8"):
|
|
error_data = json.loads(data_msg.decode("utf-8"))
|
|
error_msg = error_data['errors'][0]['message']
|
|
if not data_msg.decode("utf-8"):
|
|
self.sent_count += 1
|
|
self.write({
|
|
'state': 'done'
|
|
})
|
|
self.env['email.api'].create({
|
|
'name': self.subject,
|
|
'to_email_contact': data.id,
|
|
'to_email': to_email,
|
|
'recipient_name': to_name,
|
|
'company_name': to_company,
|
|
'from_email': self.from_email.id,
|
|
'temp_type': self.email_temp.id,
|
|
'temp_id': self.temp_id,
|
|
'to_email_contact_check': True,
|
|
'email_finder': self.id
|
|
})
|
|
|
|
elif error_msg:
|
|
self.env['email.api'].create({
|
|
'name': self.subject,
|
|
'to_email_contact': data.id,
|
|
'to_email': to_email,
|
|
'recipient_name': to_name,
|
|
'company_name': to_company,
|
|
'from_email': self.from_email.id,
|
|
'temp_type': self.email_temp.id,
|
|
'temp_id': self.temp_id,
|
|
'error_msg': error_msg,
|
|
'state': 'error',
|
|
'to_email_contact_check': True,
|
|
'error_check': True,
|
|
'email_finder': self.id
|
|
})
|
|
self.email_finder = self.id
|
|
self.send_grid_check = True
|
|
elif self.to_email_applicant:
|
|
api_info = self.env['ir.config_parameter'].search(
|
|
[('key', '=', "SendGrid API Key " + company_id.name + "")])
|
|
if not api_info:
|
|
raise UserError(_("It Needs API Key"))
|
|
if api_info.company_id.id == self.env.company.id:
|
|
api_key = api_info.value
|
|
if not api_key and api_key == "":
|
|
raise UserError(_("Your Company Needs an API Key"))
|
|
for data in self.to_email_applicant:
|
|
to_email = data.email_from
|
|
to_name = data.partner_name
|
|
to_company = data.company_id.name
|
|
if not to_company:
|
|
to_company = ""
|
|
temp_id = self.temp_id
|
|
payload = ""
|
|
if to_email:
|
|
payload = "{\"personalizations\":[{\"to\":[{\"email\":\"" + to_email + "\"}],\"dynamic_template_data\":{\"firstname\":\"" + to_name + "\",\"english\":\"true\",\"company\":\"" + to_company + "\"},\"subject\":\"Official Mail\"}],\"from\":{\"email\":\"" + from_email + "\",\"name\":\"" + from_name + "\"},\"template_id\":\"" + temp_id + "\"}"
|
|
|
|
headers = {
|
|
'authorization': "Bearer " + api_key + "",
|
|
'content-type': "application/json"
|
|
}
|
|
|
|
conn.request("POST", "/v3/mail/send", payload, headers)
|
|
|
|
res = conn.getresponse()
|
|
data_msg = res.read()
|
|
|
|
error_msg = ''
|
|
if data_msg.decode("utf-8"):
|
|
error_data = json.loads(data_msg.decode("utf-8"))
|
|
error_msg = error_data['errors'][0]['message']
|
|
if not data_msg.decode("utf-8"):
|
|
self.sent_count += 1
|
|
self.write({
|
|
'state': 'done'
|
|
})
|
|
self.env['email.api'].create({
|
|
'name': self.subject,
|
|
'to_email_applicant': data.id,
|
|
'to_email': to_email,
|
|
'recipient_name': to_name,
|
|
'company_name': to_company,
|
|
'from_email': self.from_email.id,
|
|
'temp_type': self.email_temp.id,
|
|
'temp_id': self.temp_id,
|
|
'to_email_applicant_check': True,
|
|
'email_finder': self.id
|
|
})
|
|
|
|
elif error_msg:
|
|
self.env['email.api'].create({
|
|
'name': self.subject,
|
|
'to_email_applicant': data.id,
|
|
'to_email': to_email,
|
|
'recipient_name': to_name,
|
|
'company_name': to_company,
|
|
'from_email': self.from_email.id,
|
|
'temp_type': self.email_temp.id,
|
|
'temp_id': self.temp_id,
|
|
'error_msg': error_msg,
|
|
'state': 'error',
|
|
'email_finder': self.id,
|
|
'to_email_applicant_check': True,
|
|
'error_check': True
|
|
})
|
|
self.email_finder = self.id
|
|
self.send_grid_check = True
|
|
|
|
@api.onchange('email_temp', 'mailing_model_id', 'contact_list_ids')
|
|
def temp_details(self):
|
|
"""
|
|
function used for filling subject and recipients emails
|
|
based on template and recipient emails
|
|
|
|
"""
|
|
if self.email_temp:
|
|
self.temp_check = True
|
|
self.subject = self.email_temp.ver_subject
|
|
self.temp_id = self.email_temp.temp_id
|
|
self.body_html = self.email_temp.temp_cont
|
|
self.body_arch = self.email_temp.temp_cont
|
|
else:
|
|
self.temp_check = False
|
|
|
|
if self.mailing_model_real == "sale.order" or self.mailing_model_real == "event.registration" or self.mailing_model_real == "event.track":
|
|
self.to_email_contact = False
|
|
self.to_email_lead = False
|
|
self.to_email_applicant = False
|
|
self.mailing_domain = "[]"
|
|
for mass_mailing in self:
|
|
mai_data = mass_mailing.sudo()._get_recipients()
|
|
email_ids = self.env[self.mailing_model_real].search([('id', '=', mai_data)])
|
|
if email_ids:
|
|
self.to_email_partner = email_ids.partner_id
|
|
elif self.mailing_model_real == "crm.lead":
|
|
self.to_email_contact = False
|
|
self.to_email_partner = False
|
|
self.to_email_applicant = False
|
|
self.mailing_domain = "[]"
|
|
for mass_mailing in self:
|
|
mai_data = mass_mailing.sudo()._get_recipients()
|
|
email_ids = self.env[self.mailing_model_real].search([('id', '=', mai_data)])
|
|
if email_ids:
|
|
self.to_email_lead = email_ids
|
|
elif self.mailing_model_real == "mailing.contact":
|
|
self.to_email_partner = False
|
|
self.to_email_lead = False
|
|
self.to_email_applicant = False
|
|
self.mailing_domain = "[]"
|
|
for mass_mailing in self:
|
|
mai_data = mass_mailing.sudo()._get_recipients()
|
|
email_ids = self.env[self.mailing_model_real].search([('id', '=', mai_data)])
|
|
if email_ids:
|
|
self.to_email_contact = email_ids
|
|
if self.contact_list_ids:
|
|
email_ids = self.env[self.mailing_model_real].search(
|
|
[('id', '=', mai_data), ('list_ids', '=', self.contact_list_ids.ids)])
|
|
self.to_email_contact = email_ids
|
|
|
|
elif self.mailing_model_real == "hr.applicant":
|
|
self.to_email_contact = False
|
|
self.to_email_lead = False
|
|
self.to_email_partner = False
|
|
self.mailing_domain = "[]"
|
|
for mass_mailing in self:
|
|
mai_data = mass_mailing.sudo()._get_recipients()
|
|
email_ids = self.env[self.mailing_model_real].search([('id', '=', mai_data)])
|
|
if email_ids:
|
|
self.to_email_applicant = email_ids
|
|
|
|
else:
|
|
self.to_email_contact = False
|
|
self.to_email_lead = False
|
|
self.to_email_applicant = False
|
|
self.mailing_domain = "[]"
|
|
for mass_mailing in self:
|
|
mai_data = mass_mailing.sudo()._get_recipients()
|
|
email_ids = self.env[self.mailing_model_real].search([('id', '=', mai_data)])
|
|
if email_ids:
|
|
self.to_email_partner = email_ids
|
|
|
|
@api.onchange('mailing_domain')
|
|
def get_mails_recipients(self):
|
|
"""
|
|
function used for filtering based on domain
|
|
filter
|
|
|
|
"""
|
|
if self.mailing_model_real == "sale.order" or self.mailing_model_real == "event.registration" or self.mailing_model_real == "event.track":
|
|
for mass_mailing in self:
|
|
mai_data = mass_mailing.sudo()._get_recipients()
|
|
email_ids = self.env[self.mailing_model_real].search([('id', '=', mai_data)])
|
|
if email_ids:
|
|
self.to_email_partner = email_ids.partner_id
|
|
elif self.mailing_model_real == "crm.lead":
|
|
for mass_mailing in self:
|
|
mai_data = mass_mailing.sudo()._get_recipients()
|
|
email_ids = self.env[self.mailing_model_real].search([('id', '=', mai_data)])
|
|
if email_ids:
|
|
self.to_email_lead = email_ids
|
|
elif self.mailing_model_real == "mailing.contact":
|
|
for mass_mailing in self:
|
|
mai_data = mass_mailing.sudo()._get_recipients()
|
|
email_ids = self.env[self.mailing_model_real].search([('id', '=', mai_data)])
|
|
if email_ids:
|
|
self.to_email_contact = email_ids
|
|
elif self.mailing_model_real == "hr.applicant":
|
|
for mass_mailing in self:
|
|
mai_data = mass_mailing.sudo()._get_recipients()
|
|
email_ids = self.env[self.mailing_model_real].search([('id', '=', mai_data)])
|
|
if email_ids:
|
|
self.to_email_applicant = email_ids
|
|
else:
|
|
for mass_mailing in self:
|
|
mai_data = mass_mailing.sudo()._get_recipients()
|
|
email_ids = self.env[self.mailing_model_real].search([('id', '=', mai_data)])
|
|
if email_ids:
|
|
self.to_email_partner = email_ids
|
|
|
|
@api.onchange('to_email_partner', 'to_email_lead', 'to_email_contact', 'to_email_applicant')
|
|
def show_hide_fields(self):
|
|
"""
|
|
function is used for Enabling Needed
|
|
recipient mail fields by changing check box
|
|
values.
|
|
|
|
"""
|
|
if self.to_email_partner:
|
|
self.to_email_partner_check = True
|
|
else:
|
|
self.to_email_partner_check = False
|
|
if self.to_email_lead:
|
|
self.to_email_lead_check = True
|
|
else:
|
|
self.to_email_lead_check = False
|
|
if self.to_email_contact:
|
|
self.to_email_contact_check = True
|
|
else:
|
|
self.to_email_contact_check = False
|
|
if self.to_email_applicant:
|
|
self.to_email_applicant_check = True
|
|
else:
|
|
self.to_email_applicant_check = False
|
|
|
|
def _action_view_documents_filtered(self, view_filter):
|
|
"""
|
|
function is used for returning send view in
|
|
needed recipient tree view
|
|
|
|
"""
|
|
if view_filter == 'sent' and self.temp_id:
|
|
res_ids = []
|
|
for mass_mailing in self:
|
|
mai_data = mass_mailing.sudo()._get_recipients()
|
|
res_ids = self.env[self.mailing_model_real].search([('id', '=', mai_data)])
|
|
model_name = self.env['ir.model']._get(self.mailing_model_real).display_name
|
|
return {
|
|
'name': model_name,
|
|
'type': 'ir.actions.act_window',
|
|
'view_mode': 'tree',
|
|
'res_model': self.mailing_model_real,
|
|
'domain': [('id', 'in', res_ids.ids)],
|
|
'context': dict(self._context, create=False)
|
|
}
|
|
else:
|
|
return super(SendGridEmail, self)._action_view_documents_filtered(view_filter)
|
|
|
|
def _compute_statistics(self):
|
|
"""
|
|
function is used for computing Send mails Smart button
|
|
count
|
|
|
|
"""
|
|
self.env.cr.execute("""
|
|
SELECT
|
|
m.id as mailing_id,
|
|
COUNT(s.id) AS expected,
|
|
COUNT(CASE WHEN s.sent is not null THEN 1 ELSE null END) AS sent,
|
|
COUNT(CASE WHEN s.scheduled is not null AND s.sent is null AND s.exception is null AND s.ignored is null AND s.bounced is null THEN 1 ELSE null END) AS scheduled,
|
|
COUNT(CASE WHEN s.scheduled is not null AND s.sent is null AND s.exception is null AND s.ignored is not null THEN 1 ELSE null END) AS ignored,
|
|
COUNT(CASE WHEN s.sent is not null AND s.exception is null AND s.bounced is null THEN 1 ELSE null END) AS delivered,
|
|
COUNT(CASE WHEN s.opened is not null THEN 1 ELSE null END) AS opened,
|
|
COUNT(CASE WHEN s.clicked is not null THEN 1 ELSE null END) AS clicked,
|
|
COUNT(CASE WHEN s.replied is not null THEN 1 ELSE null END) AS replied,
|
|
COUNT(CASE WHEN s.bounced is not null THEN 1 ELSE null END) AS bounced,
|
|
COUNT(CASE WHEN s.exception is not null THEN 1 ELSE null END) AS failed
|
|
FROM
|
|
mailing_trace s
|
|
RIGHT JOIN
|
|
mailing_mailing m
|
|
ON (m.id = s.mass_mailing_id)
|
|
WHERE
|
|
m.id IN %s
|
|
GROUP BY
|
|
m.id
|
|
""", (tuple(self.ids),))
|
|
for row in self.env.cr.dictfetchall():
|
|
total = row['expected'] = (row['expected'] - row['ignored']) or 1
|
|
row['received_ratio'] = 100.0 * row['delivered'] / total
|
|
row['opened_ratio'] = 100.0 * row['opened'] / total
|
|
row['clicks_ratio'] = 100.0 * row['clicked'] / total
|
|
row['replied_ratio'] = 100.0 * row['replied'] / total
|
|
row['bounced_ratio'] = 100.0 * row['bounced'] / total
|
|
self.browse(row.pop('mailing_id')).update(row)
|
|
for mail in self:
|
|
if mail.temp_id:
|
|
mail.sent = mail.sent_count
|
|
else:
|
|
return super(SendGridEmail, self)._compute_statistics()
|
|
|