Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Email Service #5

Merged
merged 21 commits into from
Jun 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions apps/accounts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@

from apps.accounts.validators import percentage_validator
from manage_content_service.settings.base import VOUCHER_CODE_LENGTH, DISCOUNT_CODE_LENGTH, PURCHASE_UNIQ_CODE_LENGTH
from proxies.sms_system.main import SMS_CODE_DELAY, SMS_CODE_LENGTH, get_sms_service_proxy
from proxies.sms_system.settings import SMS_CODE_DELAY, SMS_CODE_LENGTH
from proxies.sms_system.sms_service_facade import SMSServiceFacade


class User(AbstractUser):
Expand Down Expand Up @@ -385,10 +386,8 @@ class VerificationType(models.TextChoices):
objects = VerificationCodeManager()

def notify(self, verification_type, party_display_name='سپید'):
sms_service_proxy = get_sms_service_proxy(
type='kavenegar', token='todo')
sms_service_proxy.send_otp(
self.phone_number, verification_type, token=party_display_name, token2=str(self.code))
sms_service_facade = SMSServiceFacade(provider='kavenegar')
sms_service_facade.send_otp(self.phone_number, verification_type, token=party_display_name, token2=str(self.code))

def __str__(self):
return f'{self.phone_number}\'s code is: {self.code} {"+" if self.is_valid else "-"}'
Expand Down
2 changes: 1 addition & 1 deletion apps/accounts/serializers/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from errors.error_codes import serialize_error
from manage_content_service.settings.base import DISCOUNT_CODE_LENGTH
from proxies.sms_system.main import SMS_CODE_LENGTH
from proxies.sms_system.settings import SMS_CODE_LENGTH
from ..models import User, VerificationCode, EducationalInstitute, School, University, SchoolStudentship, Studentship, \
AcademicStudentship, Merchandise, DiscountCode, Purchase
from ..validators import phone_number_validator, grade_validator, price_validator
Expand Down
9 changes: 4 additions & 5 deletions apps/fsm/views/registration_receipt_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from apps.fsm.permissions import IsRegistrationReceiptOwner, IsReceiptsFormModifier
from apps.fsm.serializers.answer_sheet_serializers import RegistrationReceiptSerializer, RegistrationStatusSerializer
from apps.fsm.serializers.certificate_serializer import create_certificate
from proxies.sms_system.main import get_sms_service_proxy
from proxies.sms_system.sms_service_facade import SMSServiceFacade


class RegistrationReceiptViewSet(GenericViewSet, RetrieveModelMixin, DestroyModelMixin):
Expand Down Expand Up @@ -82,11 +82,10 @@ def validate(self, request, pk=None):

# todo: fix academy name
if older_status != receipt.status:
sms_service_proxy = get_sms_service_proxy(
type='kavenegar', token='todo')
sms_service_proxy.send_otp(
sms_service_facade = SMSServiceFacade(provider='kavenegar')
sms_service_facade.send_otp(
receptor_phone_number=receipt.user.phone_number,
type=sms_service_proxy.RegularSMSTypes.UpdateRegistrationReceiptState,
type=sms_service_facade.RegularSMSTypes.UpdateRegistrationReceiptState,
# todo: get real academy name from mps
token='کاموا',
token2=receipt.answer_sheet_of.program_or_fsm.name
Expand Down
390 changes: 390 additions & 0 deletions assets/greeting_mail.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion errors/error_codes.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logging
from rest_framework.exceptions import ValidationError

from proxies.sms_system.main import SMS_CODE_LENGTH
from proxies.sms_system.settings import SMS_CODE_LENGTH

logger = logging.getLogger(__name__)

Expand Down
3 changes: 3 additions & 0 deletions manage_content_service/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from manage_content_service.celery_app import app as celery_app

__all__ = ("celery_app",)
7 changes: 7 additions & 0 deletions manage_content_service/celery_app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import os
from celery import Celery

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'manage_content_service.settings.development')
app = Celery()
app.config_from_object('django.conf:settings', namespace="CELERY")
app.autodiscover_tasks()
60 changes: 21 additions & 39 deletions manage_content_service/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ def get_environment_var(var_name, default, prefixed=True):
return os.getenv(var_name, default)


CORS_ORIGIN_ALLOW_ALL = True

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(
os.path.dirname(os.path.abspath(__file__))))
Expand All @@ -43,6 +45,8 @@ def get_environment_var(var_name, default, prefixed=True):
'rest_framework.authtoken',
'import_export',
'drf_yasg',
'celery',
'messenger',
'polymorphic',
'django_extensions',
'django_filters',
Expand Down Expand Up @@ -72,26 +76,6 @@ def get_environment_var(var_name, default, prefixed=True):
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# multi-lingual settings below
# LANGUAGES = [
# ('en', _('English')),
# ('fa', _('Persian')),
# ]

# USE_I18N = True
#
# USE_L10N = True
#
# LANGUAGE_CODE = 'en'
#
# LOCALE_PATHS = [
# os.path.join(BASE_DIR, 'locale'),
# ]
# multilingual settings above

CORS_ORIGIN_ALLOW_ALL = True

ROOT_URLCONF = 'manage_content_service.urls'

TEMPLATES = [
{
Expand All @@ -109,6 +93,7 @@ def get_environment_var(var_name, default, prefixed=True):
},
]


WSGI_APPLICATION = 'manage_content_service.wsgi.application'

# Password validation
Expand Down Expand Up @@ -151,31 +136,17 @@ def get_environment_var(var_name, default, prefixed=True):
MEDIA_URL = '/api/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

EMAIL_HOST = 'smtp.zoho.com'
EMAIL_HOST_USER = 'info@rastaiha.ir'
EMAIL_HOST_PASSWORD = 'ET6vmrh.$gHZFjL'
EMAIL_PORT = 587
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_USE_TLS = True
EMAIL_USE_SSL = False
DEFAULT_FROM_EMAIL = "Rastaiha <" + EMAIL_HOST_USER + ">"

# Activate Django-Heroku.

OK_STATUS = 'ok'
ERROR_STATUS = 'err'
HELP_STATUS = 'help'

THUMBNAIL_ALIASES = {
'': {
'avatar': {'size': (80, 80), 'crop': True},
},
}
EMAIL_PORT = 587
EMAIL_HOST_USER = 'sepid.platform@gmail.com'
EMAIL_HOST_PASSWORD = 'tmyz glmk cjsj urnw'

STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'

CONSTANTS = {
"PAGINATION_NUMBER": 50,

}

# Custom user model
Expand Down Expand Up @@ -227,6 +198,17 @@ def get_environment_var(var_name, default, prefixed=True):
PURCHASE_UNIQ_CODE_LENGTH = 10


########## Celery ##########

CELERY_TIMEZONE = TIME_ZONE
CELERY_TASK_TRACK_STARTED = True
CELERY_TASK_TIME_LIMIT = 30 * 60
ROOT_URLCONF = 'manage_content_service.urls'
CELERY_BROKER_URL = get_environment_var('BROKER_URL', 'amqp://')


########## Zarrinpal Payment ##########

def GET_PAYMENT_CALLBACK_URL(domain, status):
PAYMENT = {
'success': f'http://{domain}/message/payment/success',
Expand Down
2 changes: 2 additions & 0 deletions manage_content_service/settings/development.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

ALLOWED_HOSTS = ['*']



# Database
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases

Expand Down
1 change: 1 addition & 0 deletions manage_content_service/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
path('api/report/', include('apps.report.urls')),
path('api/scoring/', include('apps.scoring.urls')),
path('test/hi/', say_hello),
path('email/' , include('messenger.urls')),
# https://pypi.org/project/django-link-shortener/
path('s/', include('shortener.urls')),
]
Expand Down
Empty file added messenger/__init__.py
Empty file.
3 changes: 3 additions & 0 deletions messenger/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.contrib import admin

# Register your models here.
6 changes: 6 additions & 0 deletions messenger/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class MessengerConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'messenger'
Empty file.
3 changes: 3 additions & 0 deletions messenger/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.db import models

# Create your models here.
15 changes: 15 additions & 0 deletions messenger/tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from celery import shared_task
from django.core.mail import EmailMessage


@shared_task()
def send_email_task(subject, recipients_emails, body):
sender_email = 'sepid.platform@gmail.com'
mail = EmailMessage(subject=subject, body=body,
from_email=sender_email, to=recipients_emails)
mail.content_subtype = 'html'
try:
mail.send()
return True
except:
return False
3 changes: 3 additions & 0 deletions messenger/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.
6 changes: 6 additions & 0 deletions messenger/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.urls import path
from messenger.views import *

urlpatterns = [
path('test/', send_email)
]
49 changes: 49 additions & 0 deletions messenger/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import os
from django.http import HttpResponse
from messenger.tasks import send_email_task
from manage_content_service.settings.base import BASE_DIR


import requests
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.shortcuts import redirect

@csrf_exempt
def send_email(request):
if request.method == 'POST':
email_data = {
# todo: convert it to recipients:
"email": request.POST.get("email"),
"subject": request.POST.get("subject"),
"body": request.POST.get("body")
# todo: add a field for choosing template
}
response = requests.post("http://127.0.0.1:8080/send-email/", json=email_data)

if response.status_code == 200:
return JsonResponse({"message": "Email has been sent"}, status=200)
else:
return JsonResponse({"error": "Failed to send email"}, status=500)

return JsonResponse({"error": "Invalid request method"}, status=405)



# def send_email(request):
# html_content =os.path.join(BASE_DIR, "assets/greeting_mail.html")
# html_content= open(html_content, "r", encoding="utf-8").read()
# send_emailQeue.delay("ehsna" , "ehsan.ghechisaz82@gmail.com" , html_content)
# return HttpResponse("goi")


# def send_email(request):
# subject = 'Subject of the email'
# message = 'This is the message body.'
# from_email = 'your_email@gmail.com' # Sender's email address
#
# # List of recipient email addresses
# recipient_list = ['ehsan.ghechisaz82@gmail.com']
#
# send_mail(subject, message, from_email, recipient_list)
# return HttpResponse('Email sent successfully!')
7 changes: 7 additions & 0 deletions proxies/email_service/send_email.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# email api: https://smtp.sepid.org/send-email/

# todo: remove messenger app

def send_email():
# todo
pass
15 changes: 9 additions & 6 deletions proxies/sms_system/kavenegar.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,15 @@

from kavenegar import *

from proxies.sms_system.main import SMSServiceProxy
from proxies.sms_system.sms_service_interface import SMSService


class KaveNegarSMSServiceProxy(SMSServiceProxy):
class KaveNegarSMSService(SMSService):

def __init__(self, token) -> None:
def __init__(self, token: str) -> None:
super().__init__()
self.api = KavenegarAPI(token)

def send_sms(self):
pass

def send_otp(self, receptor_phone_number, type, token, token2=None, token3=None):
params = {
'receptor': receptor_phone_number,
Expand All @@ -26,3 +23,9 @@ def send_otp(self, receptor_phone_number, type, token, token2=None, token3=None)
if token3:
params['token3'] = token3
self.api.verify_lookup(params)

def send_bulk(self):
return super().send_bulk()

def send_sms(self):
return super().send_sms()
35 changes: 0 additions & 35 deletions proxies/sms_system/main.py

This file was deleted.

2 changes: 2 additions & 0 deletions proxies/sms_system/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
SMS_CODE_DELAY = 5
SMS_CODE_LENGTH = 5
21 changes: 21 additions & 0 deletions proxies/sms_system/sms_service_facade.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from proxies.sms_system.sms_service_interface import SMSService


class SMSServiceFacade(SMSService):
provider: SMSService = None

def __init__(self, provider: str) -> None:
if provider == 'kavenegar':
from proxies.sms_system.kavenegar import KaveNegarSMSService
from django.conf import settings
self.provider = KaveNegarSMSService(token=settings.KAVENEGAR_TOKEN)

def send_otp(self, receptor_phone_number, action, token, token2=None, token3=None):
self.provider.send_otp(receptor_phone_number,
action, token, token2, token3)

def send_sms(self):
self.provider.send_sms()

def send_bulk(self):
self.provider.send_bulk()
Loading