用SendGrid发送邮件,但在邮箱中收不到邮件


#1

用SendGrid smtp方式发送邮件,一切显示正常,下面是app.py:

# -*- coding: utf-8 -*-
import os
from flask import Flask, flash, redirect, url_for, render_template, request
from flask_mail import Mail, Message
from flask_wtf import FlaskForm
from wtforms import StringField, TextAreaField, SubmitField
from wtforms.validators import DataRequired, Email

app = Flask(__name__)

app.config.update(
    SECRET_KEY=os.getenv('SECRET_KEY', 'secret string'),
    MAIL_SERVER=os.getenv('MAIL_SERVER'),
    MAIL_PORT=os.getenv('MAIL_PORT'),
    MAIL_USE_TSL=os.getenv('MAIL_USE_TSL'),
    MAIL_USERNAME=os.getenv('MAIL_USERNAME'),
    MAIL_PASSWORD=os.getenv('SENDGRID_API_KEY'),
    MAIL_DEFAULT_SENDER=('goldwind', os.getenv('MAIL_USERNAME'))
)

mail = Mail(app)

# send mail by SMTP
def send_smtp_mail(subject, to, body):
    message = Message(subject, recipients=[to], body=body)
    mail.send(message)

#  Form
class SubscribeForm(FlaskForm):
    name = StringField('Name', validators=[DataRequired()])
    email = StringField('Email', validators=[DataRequired(), Email()])
    submit = SubmitField('Subscribe')

@app.route('/subscribe', methods=['GET', 'POST'])
def subscribe():
    form = SubscribeForm()
    if form.validate_on_submit():
        name = form.name.data
        email = form.email.data
        send_smtp_mail('Subscribe Success!', email, name + 'Hello, thank you for subscribing Flask web!')
        return redirect(url_for('index'))
    return render_template('subscribe.html', form=form)

下面是.env文件:

MAIL_SERVER=smtp.sendgrid.net
MAIL_PORT=587
MAIL_USE_TSL=True
MAIL_USERNAME=apikey
SENDGRID_API_KEY=

下面是发送邮件时的日志:

192.168.208.1 - - [08/Mar/2019 09:55:03] "GET /subscribe HTTP/1.1" 200 -
send: 'ehlo [127.0.1.1]\r\n'
reply: b'250-smtp.sendgrid.net\r\n'
reply: b'250-8BITMIME\r\n'
reply: b'250-PIPELINING\r\n'
reply: b'250-SIZE 31457280\r\n'
reply: b'250-STARTTLS\r\n'
reply: b'250-AUTH PLAIN LOGIN\r\n'
reply: b'250 AUTH=PLAIN LOGIN\r\n'
reply: retcode (250); Msg: b'smtp.sendgrid.net\n8BITMIME\nPIPELINING\nSIZE 31457280\nSTARTTLS\nAUTH PLAIN LOGIN\nAUTH=PLAIN LOGIN'
send: 'AUTH PLAIN AGFwaWtleQBTRy5mbjNBSUpVdVFRV3ZFLUNXV2FkTGRRLno3ZDZlMGlnVExicTVkWXpmMnNQVG5Yd1F3el9BV245Q09XWDdKaFBDcWM=\r\n'
reply: b'235 Authentication successful\r\n'
reply: retcode (235); Msg: b'Authentication successful'
send: 'mail FROM:<apikey> size=340\r\n'
reply: b'250 Sender address accepted\r\n'
reply: retcode (250); Msg: b'Sender address accepted'
send: 'rcpt TO:<yubaoying@foxmail.com>\r\n'
reply: b'250 Recipient address accepted\r\n'
reply: retcode (250); Msg: b'Recipient address accepted'
send: 'data\r\n'
reply: b'354 Continue\r\n'
reply: retcode (354); Msg: b'Continue'
data: (354, b'Continue')
send: b'Content-Type: text/plain; charset="utf-8"\r\nMIME-Version: 1.0\r\nContent-Transfer-Encoding: 7bit\r\nSubject: Subscribe Success!\r\nFrom: =?utf-8?q?goldwind?= <apikey>\r\nTo: yubaoying@foxmail.com\r\nDate: Fri, 08 Mar 2019 09:55:15 +0800\r\nMessage-ID: <155201011366.4968.8553629946546010542@dev-server>\r\n\r\njjjjHello, thank you for subscribing Flask web!\r\n.\r\n'
reply: b'250 Ok: queued as zlBO4VvfR76SyV23F0MPMQ\r\n'
reply: retcode (250); Msg: b'Ok: queued as zlBO4VvfR76SyV23F0MPMQ'
data: (250, b'Ok: queued as zlBO4VvfR76SyV23F0MPMQ')
send: 'quit\r\n'
reply: b'221 See you later\r\n'
reply: retcode (221); Msg: b'See you later'
192.168.208.1 - - [08/Mar/2019 09:55:17] "POST /subscribe HTTP/1.1" 302 -
192.168.208.1 - - [08/Mar/2019 09:55:17] "GET / HTTP/1.1" 200 -

一切看着都正常,但是在邮箱里就是找不到邮件,无论是在收件箱、垃圾桶、已删除邮件。
我发送到QQ邮箱,和gmail邮箱,都收不到。


#2

SendGrid 发送邮件我也没成功过,但是我用QQ邮箱是没问题。


#3

顺便说下,dotenv似乎不会转换布尔类型。

所以你在env配置MAIL_USE_TSL=True,用os.getenv('MAIL_USE_TSL')获取的变量还是字符串,最后赋值给MAIL_USE_TSL。造成的一个bug就是如果设置了False是不会成功的。因为

>>> bool('False')
True

测试代码:

.env

boolean1 = True
boolean2 = true
boolean3 = 'true'

load.py

import os
from dotenv import load_dotenv
dotenv_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), '.env')
if os.path.exists(dotenv_path):
    load_dotenv(dotenv_path, override=True)

for b in ('boolean1', 'boolean2', 'boolean2'):
    print(type(os.getenv(b)), os.getenv(b))

# print
# <class 'str'> True
# <class 'str'> true
# <class 'str'> true


关于Flask通过.env加载环境变量的两个坑
#4

受教了。
我改成这样了,不过还是不行,我再想是不是SendGrid的问题。

MAIL_USE_TSL=True,

#5

已经成功了,找到原因了。
我最开始用国内的邮箱注册的SendGrid,一直有问题,后来我用gmail重新注册,就没问题了。


#6

原来如此,原来如此!看来我以前不成功也是因为用了国内邮箱。