قمت بتهيئة الاعدادات لدي في Django كما هو مذكور في الوثائق
#setting.py
EMAIL_HOST = 'smtp.mailgun.org'
EMAIL_PORT = 587
#مفتاح المستخدم الذي حصلت عليه من من موقع الخدمة
EMAIL_HOST_USER = XXXXXXXXXXXXXXXXXX
#كلمة سر المستخدم الذي حصلت عليه من من موقع الخدمة
EMAIL_HOST_PASSWORD = XXXXXXXXXXXXXXXXXX
EMAIL_USE_TLS = True
ثم إنشأت ملف لتجربة ارسال اول رسالة الكترونية
#send_email_test.py
import smtplib
from email.mime.text import MIMEText
msg = MIMEText('Testing some Mailgun awesomness')
msg['Subject'] = "Hello test from send_email_test.py"
msg['From'] = "[email protected]"
msg['To'] = "[email protected]"
s = smtplib.SMTP('smtp.mailgun.org', 587)
# import variable from settings in my project
from django.conf import settings
s.login(settings.EMAIL_HOST_USER, settings.EMAIL_HOST_PASSWORD)
s.sendmail(msg['From'], msg['To'], msg.as_string())
print('done, has been sent!')
s.quit()
تحققت من البريد الوارد وفعلا الرسالة وصلت خلال ثوانٍ.
لكن بعد التجربة على أكثر من ايميل وانشاء اكثر من حساب احيانا تصل الرسالة وفي بعض الحالات لا تصل !
حاولت الوصول الى لوحة التحكم في mailgun وذهبت للسجلات فوجد الرسائل مكتوب بجانبها Delivered
ونفس الايميلات التي لم تنجح العملية معها جربتها ضمن ملف send_email_test.py وكانت تصل الرسائل بنفس اللحظة
احيانا تصل واحيانا اخرى لا تصل وفي لوحة التحكم دائماً اجدها Delivered هل المشكلة من الخدمة وكيف تعمل من ملف send_email_test.py باستمرار ؟!
اترك الاجابة للمختصين
جميل جداً انا استخدم مكتبة allauth بطبيعة الحال المكتبة مصصمة لارسال البريد للمستخدم في عدة حالات ومنها التسجيل ونسيان كلمة المرور
الان لو اريد ارسال هذه الرسائل عن طريق api هل سأتبع كود المصدر الخاص ب allauth و اقوم بتغيير دالة الارسال بحيث تستخدم json للتواصل مع mailgun-api ؟
هل هذا هو الحل المفترض ؟
ولا حظت في ملف views الخاص بالمكتبة عند ارسال الايميل يتم استخدام ملف adapter.py
وداخل الملف توجد دالة ارسالة وهذا رابط الاسطر البرمجية على github
وهنا في الاسفل تم استدعاء الدالة
لدي استفسارين هل تعتبر طريقة التتبع هذه جيدة وماذا بعد ان عرفت الملف المقصود كيف سأقوم بتعديله ووضعه ضمن رملفات مشروعي وجعل المكتبة مرتبطة به بدلاً من الكود الاساسي
مرة ذكر لي @hichem2h بإنه بنهاية المطاف قام بتخصيص مكتبة خاصة به شبيهة ب allauth
يبدو انني سأضطر بالنهاية لنفس الطريق
استخدمت طريقة api لارسال البريد والجميل هي النتيجة responce العائدة من mailgun ان كانت فشلاً في الارسال او النتيجة تكون 200
قمت بتخصيص ملف adapter.py خاص بي
استخدمت الوراثة class DefaultAccountAdapter من allauth
على هذا الشكل:
#adaptr.py
from allauth.account.adapter import DefaultAccountAdapter
class MyAccountAdapter(DefaultAccountAdapter):
#my custum funtcions here
في مصادر allauth على github الدالة المسؤولة عن ارسال البريد هي send_mail:
تقوم بتمرير الرسالة الى دالة اخرى render_mail:
الدالة وظيفتها معالجة الرسالة الالكتروني و اعادة كائن مستنسخ من EmailMessage جاهز للارسال
ثم عند عودتها تحتوي على خواص من ضمنها الارسال كما في الدالة send_mail:
تأخذ ٣ عناصر
-subject عنوان
-body محتوى البريد
-email عنوان المرسل له
ثم عدلت القيمة المرجعة من دالة render_mail
بحيث اصبح تعيد كائن Dictionarie يحتوي على subject - bodies - email - from_email
بهذا الشكل:
#adaptr.py
from django.template.loader import render_to_string
from .emailAPI import send_simple_message
from django.contrib import messages
class MyAccountAdapter(DefaultAccountAdapter):
def render_mail(self, template_prefix, email, context):
"""
Renders an e-mail to `email`. `template_prefix` identifies the
e-mail that is to be sent, e.g. "account/email/email_confirmation"
"""
subject = render_to_string('{0}_subject.txt'.format(template_prefix),
context)
# remove superfluous line breaks
subject = " ".join(subject.splitlines()).strip()
subject = self.format_email_subject(subject)
from_email = self.get_from_email()
bodies = {}
for ext in ['html', 'txt']:
try:
template_name = '{0}_message.{1}'.format(template_prefix, ext)
bodies[ext] = render_to_string(template_name,
context).strip()
except TemplateDoesNotExist:
if ext == 'txt' and not bodies:
# We need at least one body
raise
if 'txt' in bodies:
msg = {
"subject": subject,
"bodies": bodies['html'],
"from_email": from_email,
"email": [email]
}
else:
msg = {
"subject": subject,
"bodies": bodies['html'],
"from_email": from_email,
"email": [email]
}
return msg
وقمت بتعديل دالة send_mail لترسل الرسالة عبر api بهذا الشكل:
ثم اضفت رسالة تأكيد للمستخدم في حالة كان هناك خطأ في النتيجة العائدة من mailgun api
هكذا:
def send_mail(self, template_prefix, email, context):
msg = self.render_mail(template_prefix, email, context)
response = send_simple_message(msg['subject'], msg['bodies'], msg['email'])
if not response.status_code == 200:
messages.add_message(self.request, messages.ERROR, 'تم إنشاء حسابك بنجاح لكن هناك خطأ الرسالة لم تصل تحقق من عنوان بريدك ان كان صحيحا')
اخيرا لديك تعديل داخل اعدادات django لتخبره بالتعامل مع ملف adaptr الخاص بك:
#custum my Adapter
ACCOUNT_ADAPTER = 'yourapp.adapter.MyAccountAdapter'
جربت الكود وهو يعمل الان
ربما هناك طرق صحيحة اخرى لكن هذا ما استطعت الوصول له بلغتي الإنجليزية المتعبة