dify
dify copied to clipboard
fix: use smtp to send email
Description
邀请用户,发送注册邮件时,邮件一直无法发出,经过本地代码测试排查,使用 smtplib
发送邮件,会卡主,同样的 SMTP 配置,使用 aiosmtplib
能正常发送。SMTP 配置的是飞书邮箱。
另外,在部署时,dify-api
在 MODE 为 api
模式时,配置以下参数是无效的,故删除:
# Mail configuration, support: resend, smtp
MAIL_TYPE: ''
# default send from email address, if not specified
MAIL_DEFAULT_SEND_FROM: 'YOUR EMAIL FROM (eg: no-reply <[email protected]>)'
SMTP_SERVER: ''
SMTP_PORT: 587
SMTP_USERNAME: ''
SMTP_PASSWORD: ''
SMTP_USE_TLS: 'true'
# the api-key for resend (https://resend.com)
RESEND_API_KEY: ''
RESEND_API_URL: https://api.resend.com
Type of Change
- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update, included: Dify Document
- [ ] Improvement, including but not limited to code refactoring, performance optimization, and UI/UX improvement
- [ ] Dependency upgrade
How Has This Been Tested?
使用 aiosmtplib
发送邮件的测试代码:
import asyncio
from email.message import EmailMessage
import aiosmtplib
message = EmailMessage()
message["From"] = "root@localhost"
message["To"] = "[email protected]"
message["Subject"] = "Hello World!"
message.set_content("Sent via aiosmtplib")
asyncio.run(aiosmtplib.send(message, hostname="127.0.0.1", port=25))
Suggested Checklist:
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] My changes generate no new warnings
- [ ] I ran
dev/reformat
(backend) andcd web && npx lint-staged
(frontend) to appease the lint gods - [ ]
optional
I have made corresponding changes to the documentation - [ ]
optional
I have added tests that prove my fix is effective or that my feature works - [ ]
optional
New and existing unit tests pass locally with my changes
aiosmtplib is the asynchronous version of smtplib, but Dify's current flask/celery doesn't support asynchronous. Have you investigated the reason for this stuck?
aiosmtplib is the asynchronous version of smtplib, but Dify's current flask/celery doesn't support asynchronous. Have you investigated the reason for this stuck?
已经知道问题所在了,如果 SMTP 服务器使用 SSL,使用 smtplib.SMTP()
初始化的时候会卡主,需要使用 smtplib.SMTP_SSL()
初始化。
I was able to reproduce this issue with an Implicit TLS server on port 465. Changing the SMTP initialization to the following code resolved the problem:
if self._use_tls:
smtp = smtplib.SMTP_SSL(self.server, self.port, timeout=10)
else:
smtp = smtplib.SMTP(self.server, self.port, timeout=10)
However, this might cause issues for Explicit TLS servers using port 587. To address this, we may need an additional flag to distinguish between these scenarios. Since custom ports can be used, it's not always clear whether the connection should use STARTTLS or Implicit TLS.
@takatost Do you have any thoughts on how to distinguish between Explicit and Implicit TLS? Implementing current fixes may cause issues for Explicit TLS servers, as they require STARTTLS implementation. However, Explicit TLS is deprecated and potentially insecure, so Dify might consider not supporting it at all.
@AnoyiX @chazzhou @rainchen
Another question should be added. The URL address for splicing the login invitation email of users must also be configured in the worker environment under services.worker.environment.CONSOLE_WEB_URL
in docker-compose.yaml file, as users cannot normally open the invitation link.
@AnoyiX @chazzhou @rainchen Another question should be added. The URL address for splicing the login invitation email of users must also be configured in the worker environment under
services.worker.environment.CONSOLE_WEB_URL
in docker-compose.yaml file, as users cannot normally open the invitation link.
@drummerglen The CONSOLE_WEB_URL
is already under the suggested env variables in the docker-compose.yaml for worker. Perhaps you can make a PR to the documents repo about configuring emails?