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

Flutter Firebase登录后发帖提示邮箱格式错误的解决咨询

解决Firebase Auth邮箱格式错误问题

问题背景

我在Flutter项目的登录注册模块中遇到了firebase_auth/invalid-email错误,即使使用硬编码的正确邮箱登录也无法解决。登录进入首页发布帖子时控制台报错,以下是相关代码和错误信息:

登录模块代码(login.dart)

import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_application_1/home.dart';
import 'package:flutter_application_1/register.dart';

class LoginPage extends StatelessWidget {
  final TextEditingController usernameController = TextEditingController();
  final TextEditingController passwordController = TextEditingController();

  Future<void> _signIn(BuildContext context) async {
    try {
      String email = usernameController.text.trim();
      String password = passwordController.text.trim();

      if (!isValidEmail(email)) {
        showDialog(
          context: context,
          builder: (BuildContext context) {
            return AlertDialog(
              title: Text('Hata'),
              content: Text('Geçersiz e-posta adresi biçimi.'),
              actions: [
                TextButton(
                  onPressed: () {
                    Navigator.pop(context);
                  },
                  child: Text('Tamam'),
                ),
              ],
            );
          },
        );
        return;
      }

      UserCredential userCredential =
          await FirebaseAuth.instance.signInWithEmailAndPassword(
        email: email,
        password: password,
      );

      // 登录成功跳转首页
      Navigator.of(context).pushReplacement(
        MaterialPageRoute(builder: (context) => MyHomePage()),
      );
    } catch (e) {
      showDialog(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            title: Text('Hata'),
            content: Text('Geçersiz kullanıcı adı ve/veya şifre.'),
            actions: [
              TextButton(
                onPressed: () {
                  Navigator.pop(context);
                },
                child: Text('Tamam'),
              ),
            ],
          );
        },
      );
    }
  }

  bool isValidEmail(String email) {
    final emailRegex = RegExp(r'^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,7}$');
    return emailRegex.hasMatch(email);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Color.fromARGB(255, 0, 0, 0),
        title: Center(
            child: Text(
          'Kome',
          style:
              TextStyle(fontFamily: "DancingScript", color: Color(0xFFFFFFFF)),
        )),
        automaticallyImplyLeading: false,
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Form(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              TextFormField(
                controller: usernameController,
                decoration: InputDecoration(labelText: 'Kullanıcı Adı'),
              ),
              TextFormField(
                controller: passwordController,
                obscureText: true,
                decoration: InputDecoration(labelText: 'Şifre'),
              ),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: () async {
                  await _signIn(context);
                },
                child: Text('Giriş Yap'),
              ),
              TextButton(
                onPressed: () {
                  Navigator.of(context).push(
                    MaterialPageRoute(builder: (context) => RegisterPage()),
                  );
                },
                child: Text('Kayıt Ol'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

注册模块代码(register.dart)

import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter_application_1/login.dart';

class RegisterPage extends StatelessWidget {
  final TextEditingController emailController = TextEditingController();
  final TextEditingController usernameController = TextEditingController();
  final TextEditingController birthDateController = TextEditingController();
  final TextEditingController passwordController = TextEditingController();
  final TextEditingController confirmPasswordController =
      TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: const Color.fromARGB(255, 0, 0, 0),
        title: const Center(
            child: Text(
          'Kome',
          style:
              TextStyle(fontFamily: "DancingScript", color: Color(0xFFFFFFFF)),
        )),
        automaticallyImplyLeading: false,
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            _buildTextField(emailController, 'E-posta'),
            _buildTextField(usernameController, 'Kullanıcı Adı'),
            _buildTextField(birthDateController, 'Doğum Tarihi'),
            _buildTextField(passwordController, 'Şifre', obscureText: true),
            _buildTextField(
              confirmPasswordController,
              'Şifreyi Tekrar Girin',
              obscureText: true,
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: () async {
                await _handleRegistration(context);
              },
              child: const Text('Kayıt Ol'),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildTextField(
    TextEditingController controller,
    String labelText, {
    bool obscureText = false,
  }) {
    return TextFormField(
      controller: controller,
      obscureText: obscureText,
      decoration: InputDecoration(labelText: labelText),
    );
  }

  Future<void> _handleRegistration(BuildContext context) async {
    try {
      UserCredential userCredential =
          await FirebaseAuth.instance.createUserWithEmailAndPassword(
        email: emailController.text,
        password: passwordController.text,
      );

      // 发送邮箱验证邮件
      await userCredential.user!.sendEmailVerification();

      await saveUserInformation(
        userCredential.user!.uid,
        usernameController.text,
        emailController.text,
        birthDateController.text,
      );

      _showSuccessDialog(context);
    } catch (e, stackTrace) {
      print('Kayıt Hatası: $e');
      print('Stack Trace: $stackTrace');
      _showErrorDialog(
        context,
        'Hata',
        'Bir hata oluştu.',
        '$e\n\nStack Trace: $stackTrace',
      );
    }
  }

  Future<void> saveUserInformation(
    String userId,
    String username,
    String email,
    String birthDate,
  ) async {
    await FirebaseFirestore.instance.collection('users').doc(userId).set({
      'username': username,
      'email': email,
      'birthDate': birthDate,
      'totalLikes': 0, // 初始点赞数设为0
      'totalComments': 0, // 初始评论数设为0
    });

    print('Saved Username: $username');
    print('Saved Email: $email');
    print('Saved Birth Date: $birthDate');
  }

  Future<void> _showSuccessDialog(BuildContext context) async {
    await showDialog<void>(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: const Text('Başarılı'),
          content: const Text('Kayıt başarıyla tamamlandı.'),
          actions: <Widget>[
            TextButton(
              onPressed: () {
                Navigator.of(context).pop(); // 关闭弹窗
                Navigator.pushReplacement(
                  context,
                  MaterialPageRoute(builder: (context) => LoginPage()),
                );
              },
              child: const Text('Tamam'),
            ),
          ],
        );
      },
    );
  }

  Future<void> _showErrorDialog(
      BuildContext context, String title, String content, dynamic error) async {
    await showDialog<void>(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text(title),
          content: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisSize: MainAxisSize.min,
            children: [
              Text(content),
              if (error != null) const SizedBox(height: 10),
              if (error != null) Text('Hata Detayı: $error'),
            ],
          ),
          actions: <Widget>[
            TextButton(
              onPressed: () {
                Navigator.of(context).pop(); // 关闭弹窗
              },
              child: const Text('Tamam'),
            ),
          ],
        );
      },
    );
  }
}

错误日志

I/FirebaseAuth( 9310): Logging in as kullanici_email with empty reCAPTCHA token W/System ( 9310): Ignoring header X-Firebase-Locale because its value was null. W/LocalRequestInterceptor( 9310): Error getting App Check token; using placeholder token instead. Error: com.google.firebase.FirebaseException: No AppCheckProvider installed. E/RecaptchaCallWrapper( 9310): Initial task failed for action RecaptchaAction(action=signInWithPassword)with exception - The email address is badly formatted. I/flutter ( 9310): Hata: [firebase_auth/invalid-email] The email address is badly formatted.

尝试的解决方法

我试过硬编码邮箱登录,问题依旧:

Future<User?> _signIn() async { 
  try { 
    UserCredential userCredential = await FirebaseAuth.instance.signInWithEmailAndPassword( 
      email: 'your_email@example.com', 
      password: 'your_password', 
    ); 
    User? user = userCredential.user; 
    return user; 
  } catch (e) { 
    print('Hata: $e'); 
    return null; 
  } 
}

解决方案

1. 修正登录逻辑的邮箱来源

登录页面输入框标注为“Kullanıcı Adı”,但代码直接将其作为邮箱使用。如果用户输入的是用户名而非邮箱,必然触发格式错误。需调整逻辑:

  • 若支持用户名登录,先从Firestore查询用户名对应的邮箱:
Future<void> _signIn(BuildContext context) async {
  try {
    String input = usernameController.text.trim();
    String password = passwordController.text.trim();

    String email;
    if (isValidEmail(input)) {
      email = input;
    } else {
      // 从Firestore查询用户名对应的邮箱
      QuerySnapshot snapshot = await FirebaseFirestore.instance
          .collection('users')
          .where('username', isEqualTo: input)
          .get();
      if (snapshot.docs.isEmpty) {
        showDialog(
          context: context,
          builder: (_) => AlertDialog(title: Text('Hata'), content: Text('Kullanıcı bulunamadı')),
        );
        return;
      }
      email = snapshot.docs.first['email'];
    }

    // 执行登录
    UserCredential userCredential =
        await FirebaseAuth.instance.signInWithEmailAndPassword(email: email, password: password);

    Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context) => MyHomePage()));
  } catch (e) {
    // 错误处理
    showDialog(
      context: context,
      builder: (_) => AlertDialog(title: Text('Hata'), content: Text(e.toString())),
    );
  }
}

2. 优化邮箱正则表达式

当前正则可能存在覆盖不全的问题,改用更通用的验证规则:

bool isValidEmail(String email) {
  return RegExp(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$').hasMatch(email);
}

3. 检查Firebase初始化与配置

确保main.dart中完成Firebase初始化:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(const MyApp());
}

同时确认google-services.json(Android)或GoogleService-Info.plist(iOS)已正确添加到项目中。

4. 处理App Check提示

日志中提到No AppCheckProvider installed,虽不是邮箱错误直接原因,但可能影响Auth流程:

  • 若不需要App Check,可在Firebase控制台关闭该功能;
  • 若需要,需在项目中添加App Check依赖并完成配置。

5. 硬编码测试注意事项

确保硬编码的邮箱是已在Firebase Auth中注册的有效账号,且密码完全匹配,无多余空格或拼写错误。


内容的提问来源于stack exchange,提问作者emirhan.akyazici

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 09:12:03