tendenci / tendenci

Tendenci - The Open Source Association Management System (AMS)
https://www.tendenci.com
Other
493 stars 202 forks source link

[Django] ERROR: Error sending newsletter #1150

Open CWalkden opened 1 year ago

CWalkden commented 1 year ago

We've had this problem on a couple of occasions now. It results in emails failing to send. We're sending emails via the Newsletters module. First we send to one group with 1028 members. Then we go back and clone that newsletter, and send it to a different group with 2730 members.

We received an error email indicating that the newsletter didn't send. See the bottom of this issue for some of the error text. It seems to suggest that the SMTP connection was unexpectedly closed.

Here is a screenshot of the Newsletters module: image It shows that the first one (bottom one on the screenshot) was submitted at 12:51, and completed sending by 1:02. The second one was submitted at 12:51 (the same minute as the first email), but sending was never completed.

Our system sends emails via Mailgun, using an SMTP connection. Through the Mailgun dashboard I can see approximately 2500 emails were sent of the 3578 emails that were intended. We asked Mailgun if there are any limits to how many emails we can send on our plan. Here is their reply:

A single API or SMTP request can have up to 1,000 recipients.
4,500 API requests can be made per IP per minute for a maximum of 4,500,000 emails per IP (submitting the request to Mailgun) per minute. Exceeding this limit results in rejection messages being returned for each additional API call until this threshold is reset
3,500 SMTP requests can be made per IP per minute for a maximum of 3,500,000 emails per IP (submitting the request to Mailgun) per minute. Exceeding this limit results in rejection messages being returned for each additional SMTP call until this threshold is reset
500,000 Queued messages at any given time. As such, if you send any further messages to our service once reaching this level, the domain will be temporarily disabled and the Messages API response will indicate requests are temporarily rejected.

It doesn't seem like we should be hitting any of those limits.

Error email text:

Error sending newsletter https://aeva.asn.au/newsletters/view/details/845/...

Traceback (most recent call last): File "/srv/tendenci/environment.py-3.8/lib/python3.8/site-packages/tendenci/apps/newsletters/management/commands/send_newsletter.py", line 216, in handle self.send_newsletter(newsletter_id) File "/srv/tendenci/environment.py-3.8/lib/python3.8/site-packages/tendenci/apps/newsletters/management/commands/send_newsletter.py", line 149, in send_newsletter email_to_send.send(connection=connection) File "/srv/tendenci/environment.py-3.8/lib/python3.8/site-packages/tendenci/apps/emails/models.py", line 130, in send msg.send(fail_silently=fail_silently) File "/srv/tendenci/environment.py-3.8/lib/python3.8/site-packages/django/core/mail/message.py", line 284, in send return self.get_connection(fail_silently).send_messages([self]) File "/srv/tendenci/environment.py-3.8/lib/python3.8/site-packages/django_log_email/backends.py", line 32, in send_messages return self.backend.send_messages(email_messages) File "/srv/tendenci/environment.py-3.8/lib/python3.8/site-packages/django/core/mail/backends/smtp.py", line 109, in send_messages sent = self._send(message) File "/srv/tendenci/environment.py-3.8/lib/python3.8/site-packages/django/core/mail/backends/smtp.py", line 125, in _send self.connection.sendmail(from_email, recipients, message.as_bytes(linesep='\r\n')) File "/usr/lib/python3.8/smtplib.py", line 879, in sendmail (code, resp) = self.mail(from_addr, esmtp_opts) File "/usr/lib/python3.8/smtplib.py", line 544, in mail return self.getreply() File "/usr/lib/python3.8/smtplib.py", line 403, in getreply raise SMTPServerDisconnected("Connection unexpectedly closed") smtplib.SMTPServerDisconnected: Connection unexpectedly closed

jennyq commented 1 year ago

Have you checked logs in your Mailgun dashboard under your domain?

CWalkden commented 1 year ago

Have you checked logs in your Mailgun dashboard under your domain?

Yes, but didn't see anything informative. Emails were received and sent on until they stopped.

jennyq commented 1 year ago

It does seem like you have hit the rate limit from Mailgun. I saw this happened only to the Trial plan. Are you using the Trial plan?

CWalkden commented 1 year ago

We're not on the Trial Plan, here are the plan details: image Our log indicates that Mailgun processed 10,440 emails in December.

Can you see any way that we might have exceeded any of the limits in my first post? I was looking at this with @rob-hills, and we found that Tendenci sends about two emails per second. This seems like it should be nowhere near the limits as stated.

jennyq commented 1 year ago

I cannot tell either.

Can you test if you can continue to send newsletters to a small test group? Or does it just happen to large groups?

CWalkden commented 1 year ago

Can you test if you can continue to send newsletters to a small test group? Or does it just happen to large groups?

Yes, it is working on a day-to-day basis with smaller groups. We routinely email groups of up to 500 people. Our routine emails are typically to one group (members), then immediately to another group (non-members), just like in this case. But the two groups in the problem case are much bigger than the ones we typically email. We have emailed these two large groups twice, and received a similar error on both occasions. It is a difficult problem to test, as we'll potentially annoy 2000+ people if we send a test message!

rob-hills commented 1 year ago

@jennyq This bug is still tripping us up once every month or two when we try and send our newsletter to all our users.

When it happens, we get the following Django error:

Error sending newsletter https://aeva.asn.au/newsletters/view/details/975/...

Traceback (most recent call last):
  File "/srv/tendenci/environment.py-3.8/lib/python3.8/site-packages/tendenci/apps/newsletters/management/commands/send_newsletter.py", line 216, in handle
    self.send_newsletter(newsletter_id)
  File "/srv/tendenci/environment.py-3.8/lib/python3.8/site-packages/tendenci/apps/newsletters/management/commands/send_newsletter.py", line 149, in send_newsletter
    email_to_send.send(connection=connection)
  File "/srv/tendenci/environment.py-3.8/lib/python3.8/site-packages/tendenci/apps/emails/models.py", line 130, in send
    msg.send(fail_silently=fail_silently)
  File "/srv/tendenci/environment.py-3.8/lib/python3.8/site-packages/django/core/mail/message.py", line 284, in send
    return self.get_connection(fail_silently).send_messages([self])
  File "/srv/tendenci/environment.py-3.8/lib/python3.8/site-packages/django_log_email/backends.py", line 32, in send_messages
    return self.backend.send_messages(email_messages)
  File "/srv/tendenci/environment.py-3.8/lib/python3.8/site-packages/django/core/mail/backends/smtp.py", line 109, in send_messages
    sent = self._send(message)
  File "/srv/tendenci/environment.py-3.8/lib/python3.8/site-packages/django/core/mail/backends/smtp.py", line 125, in _send
    self.connection.sendmail(from_email, recipients, message.as_bytes(linesep='\r\n'))
  File "/usr/lib/python3.8/smtplib.py", line 879, in sendmail
    (code, resp) = self.mail(from_addr, esmtp_opts)
  File "/usr/lib/python3.8/smtplib.py", line 544, in mail
    return self.getreply()
  File "/usr/lib/python3.8/smtplib.py", line 403, in getreply
    raise SMTPServerDisconnected("Connection unexpectedly closed")
smtplib.SMTPServerDisconnected: Connection unexpectedly closed

Report
Error sending newsletter https://aeva.asn.au/newsletters/view/details/975/...

Traceback (most recent call last):
  File "/srv/tendenci/environment.py-3.8/lib/python3.8/site-packages/tendenci/apps/newsletters/management/commands/send_newsletter.py", line 216, in handle
    self.send_newsletter(newsletter_id)
  File "/srv/tendenci/environment.py-3.8/lib/python3.8/site-packages/tendenci/apps/newsletters/management/commands/send_newsletter.py", line 149, in send_newsletter
    email_to_send.send(connection=connection)
  File "/srv/tendenci/environment.py-3.8/lib/python3.8/site-packages/tendenci/apps/emails/models.py", line 130, in send
    msg.send(fail_silently=fail_silently)
  File "/srv/tendenci/environment.py-3.8/lib/python3.8/site-packages/django/core/mail/message.py", line 284, in send
    return self.get_connection(fail_silently).send_messages([self])
  File "/srv/tendenci/environment.py-3.8/lib/python3.8/site-packages/django_log_email/backends.py", line 32, in send_messages
    return self.backend.send_messages(email_messages)
  File "/srv/tendenci/environment.py-3.8/lib/python3.8/site-packages/django/core/mail/backends/smtp.py", line 109, in send_messages
    sent = self._send(message)
  File "/srv/tendenci/environment.py-3.8/lib/python3.8/site-packages/django/core/mail/backends/smtp.py", line 125, in _send
    self.connection.sendmail(from_email, recipients, message.as_bytes(linesep='\r\n'))
  File "/usr/lib/python3.8/smtplib.py", line 879, in sendmail
    (code, resp) = self.mail(from_addr, esmtp_opts)
  File "/usr/lib/python3.8/smtplib.py", line 544, in mail
    return self.getreply()
  File "/usr/lib/python3.8/smtplib.py", line 403, in getreply
    raise SMTPServerDisconnected("Connection unexpectedly closed")
smtplib.SMTPServerDisconnected: Connection unexpectedly closed

Django Version: 3.2.11
Python Executable: /srv/tendenci/environment.py-3.8/bin/python3.8
Python Version: 3.8.12
Python Path: ['/srv/tendenci/website', '/srv/tendenci/environment.py-3.8/lib/python38.zip', '/srv/tendenci/environment.py-3.8/lib/python3.8', '/srv/tendenci/environment.py-3.8/lib/python3.8/lib-dynload', '/usr/lib/python3.8', '/srv/tendenci/environment.py-3.8/lib/python3.8/site-packages', '/srv/tendenci/environment.py-3.8/local/lib/python3.8/dist-packages']
Server time: Tue, 30 May 2023 11:43:00 +1000
Installed Applications:
['django_admin_bootstrapped',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.humanize',
 'django.contrib.sitemaps',
 'django.contrib.messages',
 'django.contrib.admindocs',
 'django.contrib.staticfiles',
 'django.contrib.gis',
 'formtools',
 'bootstrap3',
 'dj_pagination',
 'tagging',
 'captcha',
 'haystack',
 'tastypie',
 'timezone_field',
 'gunicorn',
 'rangefilter',
 'django_q',
 'django_otp',
 'django_otp.plugins.otp_totp',
 'django_otp.plugins.otp_hotp',
 'django_otp.plugins.otp_email',
 'django_otp.plugins.otp_static',
 'two_factor',
 'two_factor.plugins.email',
 'tendenci.libs.model_report',
 'tendenci.libs.tinymce',
 'tendenci.libs.uploader',
 'tendenci.apps.entities',
 'tendenci.apps.base',
 'tendenci.apps.site_settings',
 'tendenci.apps.contributions',
 'tendenci.apps.search',
 'tendenci.apps.notifications',
 'tendenci.apps.registration',
 'tendenci.apps.registry',
 'tendenci.apps.api_tasty',
 'tendenci.apps.invoices',
 'tendenci.apps.payments',
 'tendenci.apps.payments.stripe',
 'tendenci.apps.recurring_payments',
 'tendenci.apps.forms_builder.forms',
 'tendenci.apps.accounts',
 'tendenci.apps.files',
 'tendenci.apps.user_groups',
 'tendenci.apps.perms',
 'tendenci.apps.profiles',
 'tendenci.apps.meta',
 'tendenci.apps.tags',
 'tendenci.apps.articles',
 'tendenci.apps.jobs',
 'tendenci.apps.news',
 'tendenci.apps.stories',
 'tendenci.apps.pages',
 'tendenci.apps.events',
 'tendenci.apps.photos',
 'tendenci.apps.memberships',
 'tendenci.apps.corporate_memberships',
 'tendenci.apps.locations',
 'tendenci.apps.industries',
 'tendenci.apps.regions',
 'tendenci.apps.educations',
 'tendenci.apps.careers',
 'tendenci.apps.make_payments',
 'tendenci.apps.accountings',
 'tendenci.apps.emails',
 'tendenci.apps.email_blocks',
 'tendenci.apps.contacts',
 'tendenci.apps.robots',
 'tendenci.apps.versions',
 'tendenci.apps.event_logs',
 'tendenci.apps.categories',
 'tendenci.apps.theme_editor',
 'tendenci.libs.styled_forms',
 'tendenci.apps.newsletters',
 'tendenci.apps.redirects',
 'tendenci.apps.directories',
 'tendenci.apps.help_files',
 'tendenci.apps.resumes',
 'tendenci.apps.boxes',
 'tendenci.apps.mobile',
 'tendenci.apps.campaign_monitor',
 'tendenci.apps.theme',
 'tendenci.apps.discounts',
 'tendenci.apps.metrics',
 'tendenci.apps.navs',
 'tendenci.apps.tendenci_guide',
 'tendenci.apps.exports',
 'tendenci.apps.events.ics',
 'tendenci.apps.imports',
 'tendenci.apps.handler404',
 'tendenci.apps.reports',
 'tendenci.apps.dashboard',
 'tendenci.apps.social_media',
 'tendenci.apps.announcements',
 'tendenci.apps.forums',
 'tendenci.apps.committees',
 'tendenci.apps.chapters',
 'tendenci.apps.case_studies',
 'tendenci.apps.donations',
 'tendenci.apps.speakers',
 'tendenci.apps.staff',
 'tendenci.apps.studygroups',
 'tendenci.apps.videos',
 'tendenci.apps.testimonials',
 'tendenci.apps.social_services',
 'tendenci.apps.products',
 'tendenci.apps.explorer_extensions',
 'explorer',
 'debug_toolbar']
Installed Middleware:
['django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.common.CommonMiddleware',
 'dj_pagination.middleware.PaginationMiddleware',
 'django_otp.middleware.OTPMiddleware',
 'tendenci.apps.profiles.middleware.ForceLogoutProfileMiddleware',
 'tendenci.apps.profiles.middleware.ProfileMiddleware',
 'tendenci.apps.base.middleware.Http403Middleware',
 'tendenci.apps.redirects.middleware.RedirectMiddleware',
 'tendenci.apps.mobile.middleware.MobileMiddleware',
 'tendenci.apps.theme.middleware.RequestMiddleware',
 'tendenci.apps.base.middleware.MissingAppMiddleware',
 'tendenci.apps.base.middleware.RemoveNullByteMiddleware',
 'tendenci.apps.memberships.middleware.ExceededMaxTypesMiddleware',
 'tendenci.apps.forums.middleware.PybbMiddleware',
 'tendenci.apps.profiles.middleware.ProfileLanguageMiddleware',
 'django.middleware.locale.LocaleMiddleware',
 'debug_toolbar.middleware.DebugToolbarMiddleware']

Traceback (most recent call last):
  None

Request data not supplied

I can send our settings separately if you think they might help, obviously I'll not post them publicly here!

Googling the exception message turned up this Stackoverflow conversation which suggests we might be able to get more info with a debug option within the smtplib.SMTP object:

s = smtplib.SMTP('my.smtp.provider')
s.set_debuglevel(1)

Might it be possible to add a setting in the Tendenci Settings file, something like:

EMAIL_SMTP_DEBUG = True

that could enable this smtplib.SMTP object debugging to help troubleshoot problems like this?

jennyq commented 1 year ago

Hi @rob-hills,

It might be something to do with the mail server. Have you contacted Mailgun support? They might be able to provide some insights on that. Also, check the resource usage on your server when that happens. Did it run out of the resources?

I suppose you don't have "EMAIL_TIMEOUT" setting set up. According to django, "If unspecified, the default timeout will be the one provided by socket.getdefaulttimeout(), which defaults to None (no timeout). ". You might check that as well.

rob-hills commented 1 year ago

@jennyq , FYI we have changed over to Amazon SES without changing any other email/newsletter settings and have now been able to complete a mailout of over 3000 newsletters in one go.

I believe this indicates that the issue is to do with sending via MailGun rather than a resource issue or timeout problem. We had never got close to our MailGun account limits.

Perhaps there needs to be something in Tendenci documentation indicating that there may be compatibility issues if using MailGun for bulk emails?

jennyq commented 1 year ago

Good to hear. Thanks @rob-hills !

Not sure if it should be mentioned in docs, but definitely something to keep in mind.