{"record":{"id":"22ee304c15438fc9","repo":"langgenius/dify","slug":"email-send-ip-limit","errorCode":"email_send_ip_limit","errorMessage":"Too many emails have been sent from this IP address recently. Please try again later.","messagePattern":"Too many emails have been sent from this IP address recently\\. Please try again later\\.","errorType":"error_code","errorClass":"EmailSendIpLimitError","httpStatus":429,"severity":"warning","filePath":"api/controllers/console/auth/email_register.py","lineNumber":97,"sourceCode":"    VerificationTokenResponse,\n    EmailRegisterResetResponse,\n)\n\n\n@console_ns.route(\"/email-register/send-email\")\nclass EmailRegisterSendEmailApi(Resource):\n    @setup_required\n    @email_password_login_enabled\n    @email_register_enabled\n    @console_ns.expect(console_ns.models[EmailRegisterSendPayload.__name__])\n    @console_ns.response(200, \"Success\", console_ns.models[SimpleResultDataResponse.__name__])\n    @model_validate(EmailRegisterSendPayload)\n    def post(self, req_data: EmailRegisterSendPayload):\n        normalized_email = req_data.email.lower()\n\n        ip_address = extract_remote_ip(request)\n        if AccountService.is_email_send_ip_limit(ip_address):\n            raise EmailSendIpLimitError()\n        language = \"en-US\"\n        if req_data.language is not None and req_data.language in languages:\n            language = req_data.language\n\n        if dify_config.DEPLOYMENT_EDITION == DeploymentEdition.CLOUD and BillingService.is_email_in_freeze(\n            normalized_email\n        ):\n            raise AccountInFreezeError()\n\n        account = AccountService.get_account_by_email_with_case_fallback(req_data.email, session=db.session())\n        token = AccountService.send_email_register_email(email=normalized_email, account=account, language=language)\n        return {\"result\": \"success\", \"data\": token}\n\n\n@console_ns.route(\"/email-register/validity\")\nclass EmailRegisterCheckApi(Resource):\n    @setup_required\n    @email_password_login_enabled","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/api/controllers/console/auth/email_register.py#L79-L115","documentation":"Raised as EmailSendIpLimitError (code 'email_send_ip_limit') by POST /email-register/send when AccountService.is_email_send_ip_limit(ip_address) is true — the source IP has triggered too many registration-email sends within the configured window. Prevents email-bombing abuse.","triggerScenarios":"POST /console/api/email-register/send issued too many times from the same IP within the rate-limit window (configured in dify_config under email-send IP limits).","commonSituations":"Multiple users behind one corporate NAT/proxy all registering at once; automated tests hammering the endpoint; a single user repeatedly clicking 'resend'; CI sharing an egress IP across runs.","solutions":["Wait for the rate-limit window to elapse before requesting another registration email.","Throttle the 'resend' button on the client (e.g. 60s cooldown) to avoid tripping the IP limit.","For NAT'd offices, consider raising the configured IP send-limit or routing registration emails through distinct egress IPs.","In tests, mock AccountService.send_email_register_email instead of hitting the real endpoint."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"let attempt = 0;\nasync function sendRegisterEmail(email) {\n  try {\n    return await post('/email-register/send', { email });\n  } catch (e) {\n    if (e.code === 'email_send_ip_limit') {\n      // schedule a retry after the rate-limit window; do NOT retry immediately\n      throw e;\n    }\n    throw e;\n  }\n}","preventionTips":["Client-side cooldown (e.g. 60s) on the 'resend' button to avoid tripping the IP limit.","For NAT'd offices, plan capacity or use distinct egress IPs for registration flows.","In tests, mock the email-send service instead of hitting the endpoint."],"tags":["api","auth","email","rate-limit","registration","abuse"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}