diff --git a/apiserver/.env.example b/apiserver/.env.example index 5e60d87f8..128f5134f 100644 --- a/apiserver/.env.example +++ b/apiserver/.env.example @@ -18,15 +18,6 @@ REDIS_HOST="plane-redis" REDIS_PORT="6379" REDIS_URL="redis://${REDIS_HOST}:6379/" -# Email Settings -EMAIL_HOST="" -EMAIL_HOST_USER="" -EMAIL_HOST_PASSWORD="" -EMAIL_PORT=587 -EMAIL_FROM="Team Plane " -EMAIL_USE_TLS="1" -EMAIL_USE_SSL="0" - # AWS Settings AWS_REGION="" AWS_ACCESS_KEY_ID="access-key" diff --git a/apiserver/plane/bgtasks/analytic_plot_export.py b/apiserver/plane/bgtasks/analytic_plot_export.py index a80770c37..b171f72db 100644 --- a/apiserver/plane/bgtasks/analytic_plot_export.py +++ b/apiserver/plane/bgtasks/analytic_plot_export.py @@ -3,7 +3,7 @@ import csv import io # Django imports -from django.core.mail import EmailMultiAlternatives +from django.core.mail import EmailMultiAlternatives, get_connection from django.template.loader import render_to_string from django.utils.html import strip_tags from django.conf import settings @@ -16,6 +16,7 @@ from sentry_sdk import capture_exception from plane.db.models import Issue from plane.utils.analytics_plot import build_graph_plot from plane.utils.issue_filters import issue_filters +from plane.license.models import InstanceConfiguration row_mapping = { "state__name": "State", @@ -47,7 +48,19 @@ def send_export_email(email, slug, csv_buffer): text_content = strip_tags(html_content) csv_buffer.seek(0) - msg = EmailMultiAlternatives(subject, text_content, settings.EMAIL_FROM, [email]) + + # Configure email connection from the database + instance_configuration = InstanceConfiguration.objects.filter(key__startswith='EMAIL_').values() + connection = get_connection( + host=instance_configuration.get("EMAIL_HOST", ""), + port=int(instance_configuration.get("EMAIL_PORT", "587")), + username=instance_configuration.get("EMAIL_HOST_USER", ""), + password=instance_configuration.get("EMAIL_HOST_PASSWORD", ""), + use_tls=bool(instance_configuration.get("EMAIL_USE_TLS", "")), + use_ssl=bool(instance_configuration.get("EMAIL_USE_SSL", "")) + ) + + msg = EmailMultiAlternatives(subject=subject, text_content=text_content, from_email=settings.EMAIL_FROM, to=[email], connection=connection) msg.attach(f"{slug}-analytics.csv", csv_buffer.getvalue()) msg.send(fail_silently=False) diff --git a/apiserver/plane/bgtasks/email_verification_task.py b/apiserver/plane/bgtasks/email_verification_task.py index 9f9d06437..64cb1e6c6 100644 --- a/apiserver/plane/bgtasks/email_verification_task.py +++ b/apiserver/plane/bgtasks/email_verification_task.py @@ -1,5 +1,5 @@ # Django imports -from django.core.mail import EmailMultiAlternatives +from django.core.mail import EmailMultiAlternatives, get_connection from django.template.loader import render_to_string from django.utils.html import strip_tags from django.conf import settings @@ -11,8 +11,7 @@ from celery import shared_task from sentry_sdk import capture_exception # Module imports -from plane.db.models import User - +from plane.license.models import InstanceConfiguration @shared_task def email_verification(first_name, email, token, current_site): @@ -34,7 +33,18 @@ def email_verification(first_name, email, token, current_site): text_content = strip_tags(html_content) - msg = EmailMultiAlternatives(subject, text_content, from_email_string, [email]) + # Configure email connection from the database + instance_configuration = InstanceConfiguration.objects.filter(key__startswith='EMAIL_').values() + connection = get_connection( + host=instance_configuration.get("EMAIL_HOST", ""), + port=int(instance_configuration.get("EMAIL_PORT", "587")), + username=instance_configuration.get("EMAIL_HOST_USER", ""), + password=instance_configuration.get("EMAIL_HOST_PASSWORD", ""), + use_tls=bool(instance_configuration.get("EMAIL_USE_TLS", "")), + use_ssl=bool(instance_configuration.get("EMAIL_USE_SSL", "")) + ) + # Initiate email alternatives + msg = EmailMultiAlternatives(subject=subject, text_content=text_content, from_email=settings.EMAIL_FROM, to=[email], connection=connection) msg.attach_alternative(html_content, "text/html") msg.send() return diff --git a/apiserver/plane/bgtasks/forgot_password_task.py b/apiserver/plane/bgtasks/forgot_password_task.py index de1390f01..a7c628e6a 100644 --- a/apiserver/plane/bgtasks/forgot_password_task.py +++ b/apiserver/plane/bgtasks/forgot_password_task.py @@ -1,5 +1,5 @@ # Django imports -from django.core.mail import EmailMultiAlternatives +from django.core.mail import EmailMultiAlternatives, get_connection from django.template.loader import render_to_string from django.utils.html import strip_tags from django.conf import settings @@ -8,6 +8,8 @@ from django.conf import settings from celery import shared_task from sentry_sdk import capture_exception +# Module imports +from plane.license.models import InstanceConfiguration @shared_task @@ -30,7 +32,18 @@ def forgot_password(first_name, email, uidb64, token, current_site): text_content = strip_tags(html_content) - msg = EmailMultiAlternatives(subject, text_content, from_email_string, [email]) + # Configure email connection from the database + instance_configuration = InstanceConfiguration.objects.filter(key__startswith='EMAIL_').values() + connection = get_connection( + host=instance_configuration.get("EMAIL_HOST", ""), + port=int(instance_configuration.get("EMAIL_PORT", "587")), + username=instance_configuration.get("EMAIL_HOST_USER", ""), + password=instance_configuration.get("EMAIL_HOST_PASSWORD", ""), + use_tls=bool(instance_configuration.get("EMAIL_USE_TLS", "")), + use_ssl=bool(instance_configuration.get("EMAIL_USE_SSL", "")) + ) + # Initiate email alternatives + msg = EmailMultiAlternatives(subject=subject, text_content=text_content, from_email=settings.EMAIL_FROM, to=[email], connection=connection) msg.attach_alternative(html_content, "text/html") msg.send() return diff --git a/apiserver/plane/bgtasks/magic_link_code_task.py b/apiserver/plane/bgtasks/magic_link_code_task.py index 71f6db8da..eaebd3f25 100644 --- a/apiserver/plane/bgtasks/magic_link_code_task.py +++ b/apiserver/plane/bgtasks/magic_link_code_task.py @@ -1,5 +1,5 @@ # Django imports -from django.core.mail import EmailMultiAlternatives +from django.core.mail import EmailMultiAlternatives, get_connection from django.template.loader import render_to_string from django.utils.html import strip_tags from django.conf import settings @@ -8,6 +8,8 @@ from django.conf import settings from celery import shared_task from sentry_sdk import capture_exception +# Module imports +from plane.license.models import InstanceConfiguration @shared_task def magic_link(email, key, token, current_site): @@ -25,7 +27,18 @@ def magic_link(email, key, token, current_site): text_content = strip_tags(html_content) - msg = EmailMultiAlternatives(subject, text_content, from_email_string, [email]) + # Configure email connection from the database + instance_configuration = InstanceConfiguration.objects.filter(key__startswith='EMAIL_').values() + connection = get_connection( + host=instance_configuration.get("EMAIL_HOST", ""), + port=int(instance_configuration.get("EMAIL_PORT", "587")), + username=instance_configuration.get("EMAIL_HOST_USER", ""), + password=instance_configuration.get("EMAIL_HOST_PASSWORD", ""), + use_tls=bool(instance_configuration.get("EMAIL_USE_TLS", "")), + use_ssl=bool(instance_configuration.get("EMAIL_USE_SSL", "")) + ) + # Initiate email alternatives + msg = EmailMultiAlternatives(subject=subject, text_content=text_content, from_email=settings.EMAIL_FROM, to=[email], connection=connection) msg.attach_alternative(html_content, "text/html") msg.send() return diff --git a/apiserver/plane/bgtasks/project_invitation_task.py b/apiserver/plane/bgtasks/project_invitation_task.py index 8b8ef6e48..1a3bb1832 100644 --- a/apiserver/plane/bgtasks/project_invitation_task.py +++ b/apiserver/plane/bgtasks/project_invitation_task.py @@ -1,5 +1,5 @@ # Django imports -from django.core.mail import EmailMultiAlternatives +from django.core.mail import EmailMultiAlternatives, get_connection from django.template.loader import render_to_string from django.utils.html import strip_tags from django.conf import settings @@ -10,6 +10,7 @@ from sentry_sdk import capture_exception # Module imports from plane.db.models import Project, User, ProjectMemberInvite +from plane.license.models import InstanceConfiguration @shared_task @@ -43,7 +44,18 @@ def project_invitation(email, project_id, token, current_site): project_member_invite.message = text_content project_member_invite.save() - msg = EmailMultiAlternatives(subject, text_content, from_email_string, [email]) + # Configure email connection from the database + instance_configuration = InstanceConfiguration.objects.filter(key__startswith='EMAIL_').values() + connection = get_connection( + host=instance_configuration.get("EMAIL_HOST", ""), + port=int(instance_configuration.get("EMAIL_PORT", "587")), + username=instance_configuration.get("EMAIL_HOST_USER", ""), + password=instance_configuration.get("EMAIL_HOST_PASSWORD", ""), + use_tls=bool(instance_configuration.get("EMAIL_USE_TLS", "")), + use_ssl=bool(instance_configuration.get("EMAIL_USE_SSL", "")) + ) + # Initiate email alternatives + msg = EmailMultiAlternatives(subject=subject, text_content=text_content, from_email=settings.EMAIL_FROM, to=[email], connection=connection) msg.attach_alternative(html_content, "text/html") msg.send() return diff --git a/apiserver/plane/bgtasks/workspace_invitation_task.py b/apiserver/plane/bgtasks/workspace_invitation_task.py index 94be6f879..9ac8690bc 100644 --- a/apiserver/plane/bgtasks/workspace_invitation_task.py +++ b/apiserver/plane/bgtasks/workspace_invitation_task.py @@ -1,5 +1,5 @@ # Django imports -from django.core.mail import EmailMultiAlternatives +from django.core.mail import EmailMultiAlternatives, get_connection from django.template.loader import render_to_string from django.utils.html import strip_tags from django.conf import settings @@ -12,7 +12,7 @@ from slack_sdk.errors import SlackApiError # Module imports from plane.db.models import Workspace, WorkspaceMemberInvite - +from plane.license.models import InstanceConfiguration @shared_task def workspace_invitation(email, workspace_id, token, current_site, invitor): @@ -47,7 +47,18 @@ def workspace_invitation(email, workspace_id, token, current_site, invitor): workspace_member_invite.message = text_content workspace_member_invite.save() - msg = EmailMultiAlternatives(subject, text_content, from_email_string, [email]) + # Configure email connection from the database + instance_configuration = InstanceConfiguration.objects.filter(key__startswith='EMAIL_').values() + connection = get_connection( + host=instance_configuration.get("EMAIL_HOST", ""), + port=int(instance_configuration.get("EMAIL_PORT", "587")), + username=instance_configuration.get("EMAIL_HOST_USER", ""), + password=instance_configuration.get("EMAIL_HOST_PASSWORD", ""), + use_tls=bool(instance_configuration.get("EMAIL_USE_TLS", "")), + use_ssl=bool(instance_configuration.get("EMAIL_USE_SSL", "")) + ) + # Initiate email alternatives + msg = EmailMultiAlternatives(subject=subject, text_content=text_content, from_email=settings.EMAIL_FROM, to=[email], connection=connection) msg.attach_alternative(html_content, "text/html") msg.send() diff --git a/apiserver/plane/settings/common.py b/apiserver/plane/settings/common.py index b6c7240af..110550f75 100644 --- a/apiserver/plane/settings/common.py +++ b/apiserver/plane/settings/common.py @@ -173,16 +173,6 @@ USE_TZ = True DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" -# Host for sending e-mail. -EMAIL_HOST = os.environ.get("EMAIL_HOST") -# Port for sending e-mail. -EMAIL_PORT = int(os.environ.get("EMAIL_PORT", 587)) -# Optional SMTP authentication information for EMAIL_HOST. -EMAIL_HOST_USER = os.environ.get("EMAIL_HOST_USER") -EMAIL_HOST_PASSWORD = os.environ.get("EMAIL_HOST_PASSWORD") -EMAIL_USE_TLS = os.environ.get("EMAIL_USE_TLS", "1") == "1" -EMAIL_USE_SSL = os.environ.get("EMAIL_USE_SSL", "0") == "1" -EMAIL_FROM = os.environ.get("EMAIL_FROM", "Team Plane ") SIMPLE_JWT = {