Karan6124 commited on
Commit
d5cf9cc
·
1 Parent(s): 2c8d190

feat: integrate Resend HTTP API support for firewall-safe email delivery

Browse files
backend/app/config/settings.py CHANGED
@@ -34,6 +34,7 @@ class Settings(BaseSettings):
34
  SMTP_PORT: int = Field(default=587)
35
  SMTP_USER: str = Field(default="")
36
  SMTP_PASSWORD: str = Field(default="")
 
37
  SMTP_FROM: str = Field(default="noreply@quantiq.io")
38
  DEVELOPER_EMAIL: str = Field(default="karanshelar8775@gmail.com")
39
 
 
34
  SMTP_PORT: int = Field(default=587)
35
  SMTP_USER: str = Field(default="")
36
  SMTP_PASSWORD: str = Field(default="")
37
+ RESEND_API_KEY: str = Field(default="")
38
  SMTP_FROM: str = Field(default="noreply@quantiq.io")
39
  DEVELOPER_EMAIL: str = Field(default="karanshelar8775@gmail.com")
40
 
backend/app/services/email_service.py CHANGED
@@ -7,6 +7,41 @@ from backend.app.config.settings import settings
7
 
8
  logger = logging.getLogger("quantiq.email")
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  def send_price_alert_email(to_email: str, ticker: str, condition: str, target_price: float, current_price: float) -> bool:
11
  """
12
  Sends a price alert notification email using SMTP config, or logs to console as a fallback.
@@ -80,6 +115,10 @@ def send_price_alert_email(to_email: str, ticker: str, condition: str, target_pr
80
  f"{text_content}\n"
81
  f"========================================")
82
 
 
 
 
 
83
  # Check if SMTP configuration is available
84
  if not settings.SMTP_HOST or not settings.SMTP_USER or not settings.SMTP_PASSWORD:
85
  logger.warning("SMTP settings not configured. E-mail simulated via logs above.")
@@ -168,6 +207,10 @@ def send_verification_email(to_email: str, code: str, raise_on_error: bool = Fal
168
  f"{text_content}\n"
169
  f"========================================")
170
 
 
 
 
 
171
  # Check if SMTP configuration is available
172
  if not settings.SMTP_HOST or not settings.SMTP_USER or not settings.SMTP_PASSWORD:
173
  logger.warning("SMTP settings not configured. Verification e-mail simulated via logs above.")
 
7
 
8
  logger = logging.getLogger("quantiq.email")
9
 
10
+ def send_email_via_resend(to_email: str, subject: str, text_content: str, html_content: str, raise_on_error: bool = False) -> bool:
11
+ """
12
+ Sends an email using the Resend HTTP API.
13
+ """
14
+ import httpx
15
+
16
+ headers = {
17
+ "Authorization": f"Bearer {settings.RESEND_API_KEY}",
18
+ "Content-Type": "application/json"
19
+ }
20
+
21
+ payload = {
22
+ "from": settings.SMTP_FROM,
23
+ "to": [to_email],
24
+ "subject": subject,
25
+ "html": html_content,
26
+ "text": text_content
27
+ }
28
+
29
+ try:
30
+ response = httpx.post("https://api.resend.com/emails", json=payload, headers=headers, timeout=10.0)
31
+ if response.status_code in (200, 201):
32
+ logger.info(f"Successfully sent email to {to_email} via Resend API")
33
+ return True
34
+
35
+ logger.error(f"Resend API returned error status {response.status_code}: {response.text}")
36
+ if raise_on_error:
37
+ raise Exception(f"Resend API error (status {response.status_code}): {response.text}")
38
+ return False
39
+ except Exception as e:
40
+ logger.error(f"Failed to connect to Resend API: {e}")
41
+ if raise_on_error:
42
+ raise e
43
+ return False
44
+
45
  def send_price_alert_email(to_email: str, ticker: str, condition: str, target_price: float, current_price: float) -> bool:
46
  """
47
  Sends a price alert notification email using SMTP config, or logs to console as a fallback.
 
115
  f"{text_content}\n"
116
  f"========================================")
117
 
118
+ # Check if Resend HTTP API should be used
119
+ if settings.RESEND_API_KEY:
120
+ return send_email_via_resend(to_email, subject, text_content, html_content)
121
+
122
  # Check if SMTP configuration is available
123
  if not settings.SMTP_HOST or not settings.SMTP_USER or not settings.SMTP_PASSWORD:
124
  logger.warning("SMTP settings not configured. E-mail simulated via logs above.")
 
207
  f"{text_content}\n"
208
  f"========================================")
209
 
210
+ # Check if Resend HTTP API should be used
211
+ if settings.RESEND_API_KEY:
212
+ return send_email_via_resend(to_email, subject, text_content, html_content, raise_on_error=raise_on_error)
213
+
214
  # Check if SMTP configuration is available
215
  if not settings.SMTP_HOST or not settings.SMTP_USER or not settings.SMTP_PASSWORD:
216
  logger.warning("SMTP settings not configured. Verification e-mail simulated via logs above.")