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

求助:如何用Node.js+MongoDB实现Android Studio应用邮箱验证

Hey there! Let’s break down how to implement email verification for your Android app using Node.js and MongoDB step by step—this is a standard flow, and I’ll walk you through each part so you can get it working smoothly.

整体流程 Overview

Here’s the big picture of how everything connects:

  1. User submits registration details (email + password) from your Android app
  2. Node.js backend creates a user in MongoDB, generates a unique verification token, and sends a confirmation email
  3. User clicks the verification link in their email
  4. Backend validates the token, marks the user as verified, and cleans up the token
  5. Android app checks the user’s verification status (either on login or via a dedicated endpoint) and adjusts the UI accordingly
1. Backend Implementation (Node.js + MongoDB)

Let’s start with the core backend logic using Express and Mongoose.

1.1 Define the User Model

First, create a Mongoose schema for your users that includes fields for verification status, token, and token expiry:

const mongoose = require('mongoose');
const bcrypt = require('bcrypt'); // For password hashing

const userSchema = new mongoose.Schema({
  email: { 
    type: String, 
    required: true, 
    unique: true,
    lowercase: true,
    trim: true
  },
  password: { 
    type: String, 
    required: true,
    minlength: 6
  },
  isVerified: { 
    type: Boolean, 
    default: false 
  },
  verificationToken: { 
    type: String 
  },
  tokenExpiresAt: { 
    type: Date 
  }
});

// Hash password before saving
userSchema.pre('save', async function(next) {
  if (!this.isModified('password')) return next();
  this.password = await bcrypt.hash(this.password, 12);
  next();
});

module.exports = mongoose.model('User', userSchema);

1.2 Generate a Verification Token

Use Node’s built-in crypto module to create a secure random token:

const crypto = require('crypto');

const generateVerificationToken = () => {
  // Generate a 64-character hex string
  return crypto.randomBytes(32).toString('hex');
};

1.3 Set Up Email Sending with Nodemailer

We’ll use nodemailer to send the verification email. Configure your email service (I’ll use Gmail as an example—make sure to use an app password if you have 2FA enabled):

const nodemailer = require('nodemailer');

// Configure transporter
const transporter = nodemailer.createTransport({
  service: 'Gmail',
  auth: {
    user: 'your-app-email@gmail.com',
    pass: 'your-app-specific-password' // Not your regular Gmail password!
  }
});

const sendVerificationEmail = async (email, token) => {
  const verificationUrl = `https://your-backend-domain.com/api/verify-email?token=${token}`;
  const mailOptions = {
    from: 'Your App Name <your-app-email@gmail.com>',
    to: email,
    subject: 'Verify Your Email to Complete Registration',
    html: `
      <p>Hi there!</p>
      <p>Thanks for signing up. Click the link below to verify your email:</p>
      <a href="${verificationUrl}">Verify My Email</a>
      <p>This link will expire in 1 hour. If you didn't create an account, you can ignore this email.</p>
    `
  };

  try {
    await transporter.sendMail(mailOptions);
    console.log('Verification email sent successfully');
  } catch (err) {
    console.error('Failed to send email:', err);
    throw new Error('Email could not be sent');
  }
};

1.4 Create Registration and Verification Endpoints

Now build the Express routes to handle registration and token verification:

const express = require('express');
const User = require('./models/User');
const generateVerificationToken = require('./utils/tokenGenerator');
const sendVerificationEmail = require('./utils/emailSender');

const router = express.Router();

// Registration endpoint
router.post('/register', async (req, res) => {
  try {
    const { email, password } = req.body;

    // Check if user already exists
    const existingUser = await User.findOne({ email });
    if (existingUser) {
      return res.status(400).json({ message: 'User already exists' });
    }

    // Generate token and set expiry (1 hour from now)
    const verificationToken = generateVerificationToken();
    const tokenExpiresAt = Date.now() + 3600000; // 60 * 60 * 1000 = 1 hour

    // Create new user
    const newUser = new User({
      email,
      password,
      verificationToken,
      tokenExpiresAt
    });

    await newUser.save();

    // Send verification email
    await sendVerificationEmail(email, verificationToken);

    res.status(201).json({ message: 'Registration successful! Please check your email to verify.' });
  } catch (err) {
    res.status(500).json({ message: 'Server error during registration', error: err.message });
  }
});

// Email verification endpoint
router.get('/verify-email', async (req, res) => {
  try {
    const { token } = req.query;

    // Find user with valid, non-expired token
    const user = await User.findOne({
      verificationToken: token,
      tokenExpiresAt: { $gt: Date.now() }
    });

    if (!user) {
      return res.status(400).send('Invalid or expired verification token. Please request a new one.');
    }

    // Mark user as verified and clean up token fields
    user.isVerified = true;
    user.verificationToken = undefined;
    user.tokenExpiresAt = undefined;
    await user.save();

    res.status(200).send('Email verified successfully! You can now log in to your app.');
  } catch (err) {
    res.status(500).send('Server error during verification');
  }
});

module.exports = router;
2. Android Side Integration

Now let’s connect your Android app to this backend.

2.1 Send Registration Request

Use Retrofit (or OkHttp) to send the registration data to your backend. Here’s a quick Retrofit example:

// Define the API interface
interface AuthApi {
    @POST("api/register")
    suspend fun register(@Body userRequest: UserRequest): Response<ResponseBody>
}

// Data class for the request body
data class UserRequest(val email: String, val password: String)

// Initialize Retrofit
val retrofit = Retrofit.Builder()
    .baseUrl("https://your-backend-domain.com/")
    .addConverterFactory(GsonConverterFactory.create())
    .build()

val authApi = retrofit.create(AuthApi::class.java)

// In your registration activity/fragment
lifecycleScope.launch {
    try {
        val response = authApi.register(UserRequest(emailEditText.text.toString(), passwordEditText.text.toString()))
        if (response.isSuccessful) {
            // Show success message to user
            Toast.makeText(context, "Check your email to verify!", Toast.LENGTH_LONG).show()
            // Navigate to login screen
        } else {
            // Handle error (e.g., user already exists)
            val errorMessage = response.errorBody()?.string() ?: "Registration failed"
            Toast.makeText(context, errorMessage, Toast.LENGTH_SHORT).show()
        }
    } catch (e: Exception) {
        Toast.makeText(context, "Network error. Please try again.", Toast.LENGTH_SHORT).show()
    }
}

2.2 Check Verification Status

When the user tries to log in, add a check to see if their email is verified. Create a backend endpoint for this:

router.get('/check-verification', async (req, res) => {
  try {
    const { email } = req.query;
    const user = await User.findOne({ email });
    if (!user) {
      return res.status(404).json({ message: 'User not found' });
    }
    res.json({ isVerified: user.isVerified });
  } catch (err) {
    res.status(500).json({ message: 'Server error' });
  }
});

Then call this from Android when the user logs in:

// Add to AuthApi interface
@GET("api/check-verification")
suspend fun checkVerification(@Query("email") email: String): Response<VerificationStatus>

data class VerificationStatus(val isVerified: Boolean)

// In login logic
lifecycleScope.launch {
    val verificationResponse = authApi.checkVerification(emailEditText.text.toString())
    if (verificationResponse.isSuccessful) {
        val isVerified = verificationResponse.body()?.isVerified ?: false
        if (!isVerified) {
            Toast.makeText(context, "Please verify your email first!", Toast.LENGTH_LONG).show()
            return@launch
        }
        // Proceed with login
    }
}
3. Key Things to Remember
  • Password Security: Always hash passwords on the backend (we used bcrypt here)—never send plain text passwords from Android.
  • Token Expiry: Setting an expiry time for verification tokens prevents old tokens from being used maliciously.
  • HTTPS: Use HTTPS for your backend to protect tokens and user data during transmission.
  • Error Handling: Add proper error handling for cases like failed email sends, invalid tokens, and network issues on both backend and Android sides.
  • Resend Verification: Consider adding a "Resend Verification Email" feature if the user didn’t get the first one—just regenerate the token and send a new email.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 10:13:12