diff --git a/schedule_mail_to_send/__manifest__.py b/schedule_mail_to_send/__manifest__.py index 7a7b2f948..89c72b4a2 100644 --- a/schedule_mail_to_send/__manifest__.py +++ b/schedule_mail_to_send/__manifest__.py @@ -21,7 +21,7 @@ ############################################################################# { 'name': 'Schedule Mail to Send', - 'version': '18.0.1.0.0', + 'version': '18.0.1.1.0', 'category': 'Discuss', 'summary': """Easily schedule your emails for future delivery""", 'description': """This module provides a function or feature that allows diff --git a/schedule_mail_to_send/doc/RELEASE_NOTES.md b/schedule_mail_to_send/doc/RELEASE_NOTES.md index 20c69e0f4..050e02aa4 100644 --- a/schedule_mail_to_send/doc/RELEASE_NOTES.md +++ b/schedule_mail_to_send/doc/RELEASE_NOTES.md @@ -4,3 +4,8 @@ #### Version 18.0.1.0.0 ##### ADD - Initial Commit for Schedule Mail to Send + +#### 04.12.2025 +#### Version 18.0.1.1.0 +##### FIX +- Fixed the issue where scheduled emails were sent immediately instead of at the scheduled time. diff --git a/schedule_mail_to_send/models/__init__.py b/schedule_mail_to_send/models/__init__.py index 698be5cd3..d008bc909 100644 --- a/schedule_mail_to_send/models/__init__.py +++ b/schedule_mail_to_send/models/__init__.py @@ -21,3 +21,4 @@ ############################################################################# from . import mail_compose_message from . import mail_activity +from . import mail_mail diff --git a/schedule_mail_to_send/models/mail_compose_message.py b/schedule_mail_to_send/models/mail_compose_message.py index fd726712e..c800a599a 100644 --- a/schedule_mail_to_send/models/mail_compose_message.py +++ b/schedule_mail_to_send/models/mail_compose_message.py @@ -57,23 +57,20 @@ class MailComposeMessage(models.TransientModel): 'scheduled_date': self.schedule_time, 'recipient_ids': partner_list, 'attachment_ids': attachment_list, + 'scheduled_user_tz': pytz.timezone(self.env.context.get('tz') or self.env.user.tz), }) # Get the user's timezone (fallback to UTC if not set) user_tz = self.env.context.get('tz') or self.env.user.tz or 'UTC' - # Get current UTC time and convert to user's timezone utc_current_datetime = fields.Datetime.now() # Naive UTC datetime local_current_datetime = fields.Datetime.context_timestamp( self.with_context(tz=user_tz), timestamp=utc_current_datetime ) - # Handle schedule_time (assumed to be UTC in the database) schedule_time = self.schedule_time - if isinstance(schedule_time, str): # If schedule_time is a string, parse it to datetime (assuming UTC) schedule_time = fields.Datetime.from_string(schedule_time) - # Convert schedule_time to user's timezone if schedule_time: schedule_time = fields.Datetime.context_timestamp( @@ -107,29 +104,31 @@ class MailComposeMessage(models.TransientModel): return {'type': 'ir.actions.client', 'tag': 'reload'} def action_send_scheduled_mail(self): - """This function is called by a scheduled action in each minute to - send the scheduled mails""" - utc_current_datetime = fields.Datetime.now() - # Access the time zone - user_tz = pytz.timezone(self.env.context.get( - 'tz') or self.env.user.tz) - # Access local time - date_today = pytz.utc.localize(utc_current_datetime).astimezone( - user_tz) - # Converted to string and removed the utc time difference - user_current_datetime = date_today.strftime( - '%Y-%m-%d %H:%M:%S') - # Again converted to datetime type and replace the seconds with 0 - user_current_date = datetime.datetime.strptime( - user_current_datetime, - "%Y-%m-%d %H:%M:%S").replace( - second=0) - scheduled_mail_rec = self.env['mail.mail'].search( - [('scheduled_date', '<=', user_current_date)]) - if scheduled_mail_rec: - for record in scheduled_mail_rec: - record.send() - planned_activity = self.env['mail.activity'].search( - [('schedule_mail_id', '=', record.id)]) - # unlink the planned activity - planned_activity.sudo().action_feedback(self) + """Executed by cron every minute. Sends emails whose scheduled datetime + has passed according to the timezone of the user who scheduled them. + """ + Mail = self.env['mail.mail'] + # Fetch all mails having schedule date set + scheduled_mails = Mail.search([('scheduled_date', '!=', False)]) + for mail in scheduled_mails: + # If no timezone stored, fallback to UTC + user_tz = mail.scheduled_user_tz or 'UTC' + # Convert current UTC time → user's timezone + user_local_now = fields.Datetime.context_timestamp( + mail.with_context(tz=user_tz), + fields.Datetime.now() + ).replace(second=0, microsecond=0) + # Convert scheduled UTC → user's timezone + scheduled_dt = fields.Datetime.context_timestamp( + mail.with_context(tz=user_tz), + mail.scheduled_date + ).replace(second=0, microsecond=0) + # If scheduled time has passed, send mail + if scheduled_dt <= user_local_now: + mail.send() + # Remove any linked scheduled activity + activity = self.env['mail.activity'].search( + [('schedule_mail_id', '=', mail.id)] + ) + if activity: + activity.sudo().action_feedback() diff --git a/schedule_mail_to_send/models/mail_mail.py b/schedule_mail_to_send/models/mail_mail.py new file mode 100644 index 000000000..008b391e1 --- /dev/null +++ b/schedule_mail_to_send/models/mail_mail.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# You can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# (LGPL v3) along with this program. +# If not, see . +# +############################################################################# +from odoo import fields, models + + +class MailMail(models.Model): + """This class is used to add fields to mail.mail model to""" + _inherit = 'mail.mail' + + scheduled_user_tz = fields.Char(string="Scheduled User Timezone", + help="Shows the timezone of the user who scheduled the mail")