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

React Native安全获取SMTP密码及后端邮件发送的安全实现咨询

安全实现React Native + PHP后端的邮件发送方案

核心安全原则

  • 绝对禁止前端处理SMTP凭证:React Native的.env变量会被打包进应用包,完全可逆向获取,任何前端存储/获取密码的方式都无安全性可言。
  • 所有邮件逻辑移至后端:前端仅负责上传图片、提交邮件内容,由PHP后端完成SMTP发送。
  • 后端接口必须做身份验证:防止非法调用接口发送垃圾邮件或窃取资源。

具体实现步骤

1. 后端接口身份验证(JWT)

使用JWT验证用户身份,确保只有已登录的合法用户能调用邮件接口。

安装依赖

composer require firebase/php-jwt

JWT验证中间件

// jwt-verify.php
<?php
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

function verifyJWT($token) {
    $secretKey = getenv('JWT_SECRET'); // 后端.env存储密钥,绝不暴露
    try {
        $decoded = JWT::decode($token, new Key($secretKey, 'HS256'));
        return (array)$decoded;
    } catch (Exception $e) {
        http_response_code(401);
        echo json_encode(['error' => '无效的身份令牌']);
        exit;
    }
}
?>

2. 后端邮件发送接口(支持多图上传)

用PHPMailer处理SMTP发送,同时验证上传文件类型、限制接口调用。

安装依赖

composer require phpmailer/phpmailer

邮件接口代码

// send-email.php
<?php
require 'vendor/autoload.php';
require 'jwt-verify.php';

// 1. 验证JWT令牌
$token = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
if (empty($token) || !str_starts_with($token, 'Bearer ')) {
    http_response_code(401);
    echo json_encode(['error' => '身份令牌缺失']);
    exit;
}
$token = substr($token, 7);
$user = verifyJWT($token);

// 2. 处理图片上传(仅允许图片类型)
$attachments = [];
if (!empty($_FILES['images'])) {
    foreach ($_FILES['images']['tmp_name'] as $key => $tmpName) {
        $fileName = $_FILES['images']['name'][$key];
        $fileType = $_FILES['images']['type'][$key];
        if (!str_starts_with($fileType, 'image/')) {
            http_response_code(400);
            echo json_encode(['error' => `不允许的文件类型:${fileName}`]);
            exit;
        }
        $attachments[] = [
            'path' => $tmpName,
            'name' => $fileName,
            'type' => $fileType
        ];
    }
}

// 3. 验证邮件必填参数
$to = $_POST['to'] ?? '';
$subject = $_POST['subject'] ?? '';
$body = $_POST['body'] ?? '';
if (empty($to) || empty($subject)) {
    http_response_code(400);
    echo json_encode(['error' => '缺少必填字段']);
    exit;
}

// 4. 配置SMTP并发送邮件
$mail = new PHPMailer\PHPMailer\PHPMailer(true);
try {
    // SMTP配置(从后端.env读取)
    $mail->isSMTP();
    $mail->Host = getenv('SMTP_HOST');
    $mail->SMTPAuth = true;
    $mail->Username = getenv('SMTP_USER');
    $mail->Password = getenv('SMTP_PASS');
    $mail->SMTPSecure = PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_STARTTLS;
    $mail->Port = 587;

    // 邮件内容
    $mail->setFrom(getenv('SMTP_USER'), '你的应用名称');
    $mail->addAddress($to);
    $mail->isHTML(true);
    $mail->Subject = $subject;
    $mail->Body = $body;

    // 添加图片附件
    foreach ($attachments as $att) {
        $mail->addAttachment($att['path'], $att['name'], PHPMailer\PHPMailer\PHPMailer::ENCODING_BASE64, $att['type']);
    }

    $mail->send();
    echo json_encode(['success' => true, 'message' => '邮件发送成功']);
} catch (Exception $e) {
    http_response_code(500);
    echo json_encode(['error' => `邮件发送失败:${$mail->ErrorInfo}`]);
}
?>

3. React Native前端调用示例

使用axios提交表单数据,带上JWT令牌,同时上传图片:

import axios from 'axios';
import { Platform } from 'react-native';
import * as ImagePicker from 'react-native-image-picker';

// 假设用户登录后已获取JWT令牌
const authToken = '用户登录返回的JWT字符串';

const sendEmail = async () => {
    // 选择多张图片
    const pickerResult = await ImagePicker.launchImageLibraryAsync({
        mediaType: 'photo',
        allowsMultipleSelection: true,
        quality: 0.8,
    });

    if (!pickerResult.canceled) {
        const formData = new FormData();
        // 添加邮件参数
        formData.append('to', '收件人邮箱@example.com');
        formData.append('subject', '测试邮件');
        formData.append('body', '<p>这是带图片的测试邮件内容</p>');

        // 添加图片文件
        pickerResult.assets.forEach((asset, index) => {
            const uri = Platform.OS === 'android' ? asset.uri : asset.uri.replace('file://', '');
            formData.append('images[]', {
                uri,
                type: asset.type,
                name: `image-${index}.${asset.type.split('/')[1]}`,
            });
        });

        try {
            const response = await axios.post('https://你的域名.com/send-email.php', formData, {
                headers: {
                    'Authorization': `Bearer ${authToken}`,
                    'Content-Type': 'multipart/form-data',
                },
            });
            console.log('发送成功:', response.data);
        } catch (error) {
            console.error('发送失败:', error.response?.data || error.message);
        }
    }
};

额外安全加固

  • 接口限流:在PHP后端添加限流逻辑(比如每个用户每分钟最多调用5次),防止接口滥用。
  • 收件人白名单:如果应用仅允许发送到特定域名/邮箱,在后端添加收件人验证。
  • 强制HTTPS:所有接口必须使用HTTPS,防止令牌和数据被明文拦截。
  • 保护后端.env:将.env文件放在web根目录外,或通过服务器配置禁止直接访问。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 06:37:08