You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Serverpod:如何通过Mailgun等服务发送验证码至应用(替代终端打印)

在Serverpod中实现验证码的短信/邮件发送(替代终端打印)

下面分邮件和短信两种方式,给出基于Mailgun、Sendgrid、通用SMTP及短信服务的具体实现方案:

一、邮件发送验证码

1. 使用Mailgun API

配置步骤

在Serverpod项目的config/config.yaml中添加Mailgun相关配置:

mailgun:
  apiKey: 'your_mailgun_api_key'
  domain: 'your_mailgun_verified_domain'
  fromEmail: 'verify@yourdomain.com'

代码实现

在你的认证Endpoint(比如auth_endpoint.dart)中添加发送方法:

import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:serverpod/serverpod.dart';

class AuthEndpoint extends Endpoint {
  Future<void> sendVerificationEmail(Session session, String email, String code) async {
    final config = session.serverpod.config;
    final apiKey = config.mailgun.apiKey;
    final domain = config.mailgun.domain;
    final fromEmail = config.mailgun.fromEmail;

    final url = Uri.parse('https://api.mailgun.net/v3/$domain/messages');
    final response = await http.post(
      url,
      headers: {
        'Authorization': 'Basic ${base64Encode(utf8.encode('api:$apiKey'))}',
      },
      body: {
        'from': fromEmail,
        'to': email,
        'subject': '你的账号验证码',
        'text': '你的验证码是:$code,5分钟内有效,请勿泄露给他人。',
      },
    );

    if (response.statusCode != 200) {
      throw Exception('邮件发送失败:${response.body}');
    }
  }
}

2. 使用Sendgrid API

配置步骤

在config/config.yaml中添加Sendgrid配置:

sendgrid:
  apiKey: 'your_sendgrid_api_key'
  fromEmail: 'verify@yourdomain.com'

代码实现

import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:serverpod/serverpod.dart';

class AuthEndpoint extends Endpoint {
  Future<void> sendVerificationEmail(Session session, String email, String code) async {
    final config = session.serverpod.config;
    final apiKey = config.sendgrid.apiKey;
    final fromEmail = config.sendgrid.fromEmail;

    final url = Uri.parse('https://api.sendgrid.com/v3/mail/send');
    final response = await http.post(
      url,
      headers: {
        'Authorization': 'Bearer $apiKey',
        'Content-Type': 'application/json',
      },
      body: jsonEncode({
        'personalizations': [{'to': [{'email': email}]}],
        'from': {'email': fromEmail},
        'subject': '你的账号验证码',
        'content': [
          {'type': 'text/plain', 'value': '你的验证码是:$code,5分钟内有效,请勿泄露给他人。'}
        ]
      }),
    );

    if (response.statusCode != 202) {
      throw Exception('邮件发送失败:${response.body}');
    }
  }
}

3. 使用通用SMTP服务器

依赖配置

在Serverpod项目的pubspec.yaml中添加邮件依赖:

dependencies:
  mailer: ^6.1.0
  smtp_server: ^6.1.0

配置步骤

在config/config.yaml中添加SMTP配置:

smtp:
  host: 'smtp.yourserver.com'
  port: 587
  username: 'your_smtp_username'
  password: 'your_smtp_password'
  fromEmail: 'verify@yourdomain.com'

代码实现

import 'package:mailer/mailer.dart';
import 'package:mailer/smtp_server.dart';
import 'package:serverpod/serverpod.dart';

class AuthEndpoint extends Endpoint {
  Future<void> sendVerificationEmail(Session session, String email, String code) async {
    final config = session.serverpod.config;
    final smtpServer = SmtpServer(
      config.smtp.host,
      port: config.smtp.port,
      username: config.smtp.username,
      password: config.smtp.password,
    );

    final message = Message()
      ..from = Address(config.smtp.fromEmail, '你的应用名称')
      ..recipients.add(email)
      ..subject = '你的账号验证码'
      ..text = '你的验证码是:$code,5分钟内有效,请勿泄露给他人。';

    try {
      await send(message, smtpServer);
    } catch (e) {
      throw Exception('邮件发送失败:$e');
    }
  }
}

二、短信发送验证码(以Twilio为例)

配置步骤

在config/config.yaml中添加Twilio配置:

twilio:
  accountSid: 'your_twilio_account_sid'
  authToken: 'your_twilio_auth_token'
  fromPhone: '+1234567890' # 你的Twilio验证号码

代码实现

import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:serverpod/serverpod.dart';

class AuthEndpoint extends Endpoint {
  Future<void> sendVerificationSms(Session session, String phoneNumber, String code) async {
    final config = session.serverpod.config;
    final accountSid = config.twilio.accountSid;
    final authToken = config.twilio.authToken;
    final fromPhone = config.twilio.fromPhone;

    final url = Uri.parse('https://api.twilio.com/2010-04-01/Accounts/$accountSid/Messages.json');
    final response = await http.post(
      url,
      headers: {
        'Authorization': 'Basic ${base64Encode(utf8.encode('$accountSid:$authToken'))}',
        'Content-Type': 'application/x-www-form-urlencoded',
      },
      body: {
        'From': fromPhone,
        'To': phoneNumber,
        'Body': '你的验证码是:$code,5分钟内有效,请勿泄露给他人。',
      },
    );

    if (response.statusCode != 201) {
      throw Exception('短信发送失败:${response.body}');
    }
  }
}

三、调用发送方法的示例逻辑

在生成验证码后,保存并调用发送方法:

import 'dart:math';
import 'package:serverpod/serverpod.dart';
import '../generated/protocol.dart';

class AuthEndpoint extends Endpoint {
  Future<String> requestVerification(Session session, String email) async {
    // 生成6位随机验证码
    final code = (Random().nextInt(900000) + 100000).toString();
    // 保存验证码到数据库(需提前定义VerificationCode模型)
    await VerificationCode.insert(session, VerificationCode(
      email: email,
      code: code,
      expiresAt: DateTime.now().add(const Duration(minutes: 5)),
    ));
    // 发送邮件验证码
    await sendVerificationEmail(session, email, code);
    // 如需发送短信,替换为:
    // await sendVerificationSms(session, phoneNumber, code);
    return '验证码已发送';
  }
}

四、注意事项

  • 所有敏感配置(API密钥、密码等)必须放在config.yaml,切勿硬编码或提交到版本控制。
  • 实现发送失败的重试机制或向Flutter客户端返回明确错误信息。
  • 验证码必须设置过期时间,验证时检查有效性。
  • 短信服务需提前完成号码验证、模板审核等平台要求的配置。

内容的提问来源于stack exchange,提问作者santhosh kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 06:57:03