from otree.api import * import os import smtplib from email.message import EmailMessage class C(BaseConstants): NAME_IN_URL = 'email_test' PLAYERS_PER_GROUP = None NUM_ROUNDS = 1 class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): pass def send_gmail_smtp(subject: str, body: str, to_email: str): gmail_user = os.environ.get("GMAIL_USER") gmail_app_pw = (os.environ.get("GMAIL_APP_PASSWORD") or "").replace(" ", "") if not gmail_user or not gmail_app_pw: raise RuntimeError("Missing GMAIL_USER or GMAIL_APP_PASSWORD environment variables.") msg = EmailMessage() msg["Subject"] = subject msg["From"] = gmail_user msg["To"] = to_email msg.set_content(body) with smtplib.SMTP("smtp.gmail.com", 587) as smtp: smtp.ehlo() smtp.starttls() smtp.login(gmail_user, gmail_app_pw) smtp.send_message(msg) class SendEmail(Page): @staticmethod def before_next_page(player, timeout_happened): to_email = os.environ.get("GMAIL_USER") # send to yourself for test send_gmail_smtp( subject="oTree Email Test ✅ (SMTP direct)", body="If you received this, SMTP works inside oTree too (without Django mail backend).", to_email=to_email, ) page_sequence = [SendEmail]