diff --git a/app/blueprints/admin/email.py b/app/blueprints/admin/email.py
index b0b54a05..6899debc 100644
--- a/app/blueprints/admin/email.py
+++ b/app/blueprints/admin/email.py
@@ -21,7 +21,7 @@ from wtforms import TextAreaField, SubmitField, StringField
from wtforms.validators import InputRequired, Length
from app.markdown import render_markdown
-from app.tasks.emails import send_user_email
+from app.tasks.emails import send_user_email, send_bulk_email as task_send_bulk
from app.utils import rank_required, addAuditLog
from . import bp
from ...models import UserRank, User, AuditSeverity
@@ -70,8 +70,7 @@ def send_bulk_email():
text = form.text.data
html = render_markdown(text)
- for user in User.query.filter(User.email.isnot(None)).all():
- send_user_email.delay(user.email, user.locale or "en", form.subject.data, text, html)
+ task_send_bulk.delay(form.subject.data, text, html)
return redirect(url_for("admin.admin_page"))
diff --git a/app/models/users.py b/app/models/users.py
index f9aef0d3..3af2feca 100644
--- a/app/models/users.py
+++ b/app/models/users.py
@@ -309,6 +309,11 @@ class EmailSubscription(db.Model):
self.blacklisted = False
self.token = None
+ @property
+ def url(self):
+ from ..utils import abs_url_for
+ return abs_url_for('users.unsubscribe', token=self.token)
+
class NotificationType(enum.Enum):
# Package / release / etc
diff --git a/app/tasks/emails.py b/app/tasks/emails.py
index 7dca096c..a74e8e75 100644
--- a/app/tasks/emails.py
+++ b/app/tasks/emails.py
@@ -14,9 +14,10 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see
{escape(text)}" msg.html = render_template("emails/base.html", subject=subject, content=html, reason=reason, sub=sub) - mail.send(msg) + if conn: + conn.send(msg) + else: + mail.send(msg) @celery.task(rate_limit="25/m") -def send_user_email(email: str, locale: str, subject: str, text: str, html=None): - with force_locale(locale or "en"): - return send_email_with_reason(email, locale, subject, text, html, - gettext("You are receiving this email because you are a registered user of ContentDB.")) +def send_user_email(email: str, locale: str, subject: str, text: str, html=None, conn=None): + return send_email_with_reason(email, locale, subject, text, html, + lazy_gettext("You are receiving this email because you are a registered user of ContentDB."), conn) @celery.task(rate_limit="25/m") def send_anon_email(email: str, locale: str, subject: str, text: str, html=None): - with force_locale(locale or "en"): - return send_email_with_reason(email, locale, subject, text, html, - gettext("You are receiving this email because someone (hopefully you) entered your email address as a user's email.")) + return send_email_with_reason(email, locale, subject, text, html, + lazy_gettext("You are receiving this email because someone (hopefully you) entered your email address as a user's email.")) def send_single_email(notification, locale): @@ -115,7 +120,7 @@ def send_single_email(notification, locale): return with force_locale(locale or "en"): - msg = Message(notification.title, recipients=[notification.user.email]) + msg = Message(notification.title, recipients=[notification.user.email], extra_headers=gen_headers(sub)) msg.body = """ New notification: {} @@ -187,3 +192,10 @@ def send_pending_notifications(): send_notification_digest(to_send, user.locale or "en") elif len(to_send) > 0: send_single_email(to_send[0], user.locale or "en") + + +@celery.task() +def send_bulk_email(subject: str, text: str, html=None): + with mail.connect() as conn: + for user in User.query.filter(User.email.isnot(None)).all(): + send_user_email(user.email, user.locale or "en", subject, text, html, conn) diff --git a/app/templates/emails/base.html b/app/templates/emails/base.html index 1ceb5a6f..5bf39d34 100644 --- a/app/templates/emails/base.html +++ b/app/templates/emails/base.html @@ -59,7 +59,7 @@
{% block footer %}
{{ reason }}
-
+
{{ _("Unsubscribe") }}
{% endblock %}