CaiYouHui后端fastapi实现

email.py 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. from fastapi import BackgroundTasks
  2. from typing import Optional
  3. import smtplib
  4. from email.mime.text import MIMEText
  5. from email.mime.multipart import MIMEMultipart
  6. from jinja2 import Template
  7. import aiosmtplib
  8. from ..config import settings
  9. import os
  10. class EmailService:
  11. def __init__(self):
  12. self.smtp_host = settings.SMTP_HOST
  13. self.smtp_port = settings.SMTP_PORT
  14. self.smtp_user = settings.SMTP_USER
  15. self.smtp_password = settings.SMTP_PASSWORD
  16. self.from_email = settings.EMAILS_FROM_EMAIL
  17. self.from_name = settings.EMAILS_FROM_NAME
  18. async def send_email_async(
  19. self,
  20. email_to: str,
  21. subject: str,
  22. html_content: str,
  23. text_content: Optional[str] = None
  24. ) -> bool:
  25. """异步发送邮件"""
  26. message = MIMEMultipart("alternative")
  27. message["Subject"] = subject
  28. message["From"] = f"{self.from_name} <{self.from_email}>"
  29. message["To"] = email_to
  30. # 添加纯文本版本
  31. if text_content:
  32. part1 = MIMEText(text_content, "plain")
  33. message.attach(part1)
  34. # 添加HTML版本
  35. part2 = MIMEText(html_content, "html")
  36. message.attach(part2)
  37. try:
  38. await aiosmtplib.send(
  39. message,
  40. hostname=self.smtp_host,
  41. port=self.smtp_port,
  42. username=self.smtp_user,
  43. password=self.smtp_password,
  44. use_tls=True,
  45. )
  46. return True
  47. except Exception as e:
  48. print(f"Error sending email: {e}")
  49. return False
  50. def send_email_sync(
  51. self,
  52. email_to: str,
  53. subject: str,
  54. html_content: str,
  55. text_content: Optional[str] = None
  56. ) -> bool:
  57. """同步发送邮件"""
  58. message = MIMEMultipart("alternative")
  59. message["Subject"] = subject
  60. message["From"] = f"{self.from_name} <{self.from_email}>"
  61. message["To"] = email_to
  62. if text_content:
  63. part1 = MIMEText(text_content, "plain")
  64. message.attach(part1)
  65. part2 = MIMEText(html_content, "html")
  66. message.attach(part2)
  67. try:
  68. with smtplib.SMTP(self.smtp_host, self.smtp_port) as server:
  69. server.starttls()
  70. server.login(self.smtp_user, self.smtp_password)
  71. server.send_message(message)
  72. return True
  73. except Exception as e:
  74. print(f"Error sending email: {e}")
  75. return False
  76. async def send_verification_email(
  77. self,
  78. email_to: str,
  79. username: str,
  80. verification_url: str,
  81. verification_code: Optional[str] = None
  82. ) -> bool:
  83. """发送验证邮件"""
  84. # 加载模板
  85. template_path = os.path.join("templates", "email", "verify_email.html")
  86. with open(template_path, "r") as f:
  87. template_str = f.read()
  88. template = Template(template_str)
  89. html_content = template.render(
  90. username=username,
  91. verification_url=verification_url,
  92. verification_code=verification_code,
  93. frontend_url=settings.FRONTEND_URL
  94. )
  95. subject = "Verify Your Email Address"
  96. text_content = f"Hello {username},\n\nPlease verify your email by clicking: {verification_url}"
  97. if verification_code:
  98. text_content += f"\n\nOr use this verification code: {verification_code}"
  99. return await self.send_email_async(email_to, subject, html_content, text_content)
  100. async def send_password_reset_email(
  101. self,
  102. email_to: str,
  103. username: str,
  104. reset_url: str
  105. ) -> bool:
  106. """发送密码重置邮件"""
  107. template_path = os.path.join("templates", "email", "reset_password.html")
  108. with open(template_path, "r") as f:
  109. template_str = f.read()
  110. template = Template(template_str)
  111. html_content = template.render(
  112. username=username,
  113. reset_url=reset_url,
  114. frontend_url=settings.FRONTEND_URL
  115. )
  116. subject = "Password Reset Request"
  117. text_content = f"Hello {username},\n\nClick here to reset your password: {reset_url}"
  118. return await self.send_email_async(email_to, subject, html_content, text_content)
  119. async def send_welcome_email(
  120. self,
  121. email_to: str,
  122. username: str
  123. ) -> bool:
  124. """发送欢迎邮件"""
  125. template_path = os.path.join("templates", "email", "welcome.html")
  126. with open(template_path, "r") as f:
  127. template_str = f.read()
  128. template = Template(template_str)
  129. html_content = template.render(
  130. username=username,
  131. frontend_url=settings.FRONTEND_URL
  132. )
  133. subject = "Welcome to Our Platform!"
  134. text_content = f"Welcome {username}! We're glad to have you on board."
  135. return await self.send_email_async(email_to, subject, html_content, text_content)
  136. email_service = EmailService()