본문 바로가기
Flutter/Package

플러터에서 문의 이메일 보내기 구현 방법 : 심층 가이드[ flutter_email_sender 패키지 ]

by Maccrey Coding 2024. 7. 26.
728x90
반응형

 

Flutter 앱에서 문의 이메일을 보내는 기능은 사용자와 소통하고 피드백을 수집하는 중요한 기능입니다.

이 블로그에서는 Flutter에서 이메일을 보내는 가장 일반적인 방법인 flutter_email_sender 패키지를 사용하는 방법을 단계별로 안내합니다.

또한, 안드로이드 11 이상 버전에서 이메일 보내기 위한 추가 설정 방법과 몇 가지 유용한 팁도 살펴보겠습니다.

 

1. flutter_email_sender 패키지 설치

먼저, flutter_email_sender 패키지를 프로젝트에 추가해야 합니다. 다음 명령을 사용하여 패키지를 설치하십시오.

flutter pub add flutter_email_sender
 

2. 기본적인 이메일 보내기

 

패키지를 설치한 후 다음과 같은 코드를 사용하여 기본적인 이메일을 보낼 수 있습니다.

import 'package:flutter_email_sender/flutter_email_sender.dart';

void _sendEmail() async {
  final Email email = Email(
    body: '본문 내용을 입력하세요.',
    subject: '제목을 입력하세요.',
    recipients: ['받는 사람 이메일 주소'],
    cc: ['CC 이메일 주소 (선택사항)'],
    bcc: ['BCC 이메일 주소 (선택사항)'],
    isHTML: false // HTML 형식 여부 (기본값: false)
  );

  try {
    await FlutterEmailSender.send(email);
    print('이메일 전송 성공!');
  } catch (error) {
    print('이메일 전송 실패: $error');
  }
}
 

위 코드에서는 Email 클래스를 사용하여 이메일 정보를 구성합니다. body, subject, recipients와 같은 필수 속성을 설정해야 하며, cc, bcc, isHTML와 같은 선택적 속성도 설정할 수 있습니다.

FlutterEmailSender.send 메서드를 사용하여 이메일을 보냅니다. 이 메서드는 Future 객체를 반환하므로 await 키워드를 사용하여 비동기적으로 결과를 처리할 수 있습니다.

 

3. 안드로이드 11 이상에서 이메일 보내기

 

안드로이드 11 이상 버전에서는 앱이 직접 이메일을 보내는 것을 제한하기 때문에 추가 설정이 필요합니다.

다음 단계를 수행하여 AndroidManifest.xml 파일에 필요한 권한을 추가해야 합니다.

  1. AndroidManifest.xml 파일을 엽니다.
  2. 다음 코드를 <manifest> 태그 안에 추가합니다.
<queries>
    <intent>
        <action android:name="android.intent.action.SENDTO" />
        <data android:scheme="mailto" />
    </intent>
</queries>
 

이 코드는 앱이 mailto 스키마를 사용하는 SENDTO 인텐트를 처리할 수 있도록 합니다.

 

4. 오류 처리 및 사용자 안내

 

이메일 전송 과정에서 오류가 발생할 수 있습니다. catch 블록을 사용하여 오류를 처리하고 사용자에게 적절한 안내 메시지를 제공하는 것이 중요합니다.

try {
  await FlutterEmailSender.send(email);
  print('이메일 전송 성공!');
} catch (error) {
  print('이메일 전송 실패: $error');
  // 사용자에게 오류 메시지 표시
  Get.defaultDialog(
    title: '오류',
    content: Text('이메일 전송에 실패했습니다.\n다시 시도하거나, 메일 앱을 사용하여 직접 보내주세요.'),
    textConfirm: '확인',
    confirmTextColor: Colors.white54,
    onConfirm: Get.back,
  );
}
 

5. 추가 팁

  • attachFile 속성을 사용하여 이메일에 파일을 첨부할 수 있습니다.
  • attachments 속성을 사용하여 여러 개의 파일을 첨부할 수 있습니다.
  • customTypeface 속성을 사용하여 이메일 본문에 사용할 글꼴을 지정할 수 있습니다.

1. 코드 예시: 실제 앱 적용

다음은 FirstWidget에서 SecondWidget로 이동하여 문의 이메일을 보내는 기능을 구현하는 예시입니다.

 

FirstWidget.dart

import 'package:flutter/material.dart';
import 'package:flutter_email_sender/flutter_email_sender.dart';
import 'second_widget.dart';

class FirstWidget extends StatefulWidget {
  @override
  _FirstWidgetState createState() => _FirstWidgetState();
}

class _FirstWidgetState extends State<FirstWidget> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('첫 번째 페이지'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => SecondWidget()),
            );
          },
          child: Text('문의하기'),
        ),
      ),
    );
  }
}
 

SecondWidget.dart

import 'package:flutter/material.dart';
import 'package:flutter_email_sender/flutter_email_sender.dart';

class SecondWidget extends StatefulWidget {
  @override
  _SecondWidgetState createState() => _SecondWidgetState();
}

class _SecondWidgetState extends State<SecondWidget> {
  final _formKey = GlobalKey<FormState>();
  final _controllerId = TextEditingController();
  final _controllerOS = TextEditingController();
  final _controllerDevice = TextEditingController();
  final _controllerContent = TextEditingController();

  @override
  void dispose() {
    _controllerId.dispose();
    _controllerOS.dispose();
    _controllerDevice.dispose();
    _controllerContent.dispose();
    super.dispose();
  }

  void _sendEmail() async {
    if (!_formKey.currentState!.validate()) {
      return;
    }

    final Email email = Email(
      body: '아래 내용을 함께 보내주시면 큰 도움이 됩니다.\n'
          '아이디: ${_controllerId.text}\n'
          'OS 버전: ${_controllerOS.text}\n'
          '기기: ${_controllerDevice.text}\n'
          '\n아래에 문의 내용을 적어주세요.\n'
          '${_controllerContent.text}',
      subject: 'Navi diary 문의 및 제휴문의',
      recipients: ['maccrey@naver.com'],
      cc: ['navi.project2023@gmail.com'],
      isHTML: false,
    );

    try {
      await FlutterEmailSender.send(email);
      print('이메일 전송 성공!');
      Navigator.pop(context); // 이전 페이지로 돌아감
    } catch (error) {
      print('이메일 전송 실패: $error');
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          backgroundColor: Colors.red,
          content: Text('이메일 전송에 실패했습니다. 다시 시도해주세요.'),
        ),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('문의하기'),
      ),
      body: Form(
        key: _formKey,
        child: SingleChildScrollView(
          padding: EdgeInsets.all(20.0),
          child: Column(
            children: [
              TextFormField(
                controller: _controllerId,
                decoration: InputDecoration(labelText: '아이디'),
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return '아이디를 입력하세요.';
                  }
                  return null;
                },
              ),
              SizedBox(height: 10.0),
              TextFormField(
                controller: _controllerOS,
                decoration: InputDecoration(labelText: 'OS 버전'),
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return 'OS 버전을 입력하세요.';
                  }
                  return null;
                },
              ),
              SizedBox(height: 10.0),
              TextFormField(
                controller: _controllerDevice,
                decoration: InputDecoration(labelText: '기기'),
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return '기기를 입력하세요.';
                  }
                  return null;
                },
              ),
              SizedBox(height: 10.0),
              TextFormField(
                controller: _controllerContent,
                maxLines: 10,
                decoration: InputDecoration(labelText: '문의 내용'),
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return '문의 내용을 입력하세요.';
                  }
                  return null;
                },
              ),
              SizedBox(height: 20.0),
              ElevatedButton(
                onPressed: _sendEmail,
                child: Text('보내기'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
 

설명

  • _formKey는 Form 위젯의 상태를 관리하는 데 사용되는 키입니다.
  • _controllerId, _controllerOS, _controllerDevice, _controllerContent 는 각각 TextFormField 위젯의 컨트롤러입니다. 사용자 입력을 저장하고 관리하는 데 사용됩니다.
  • dispose() 메서드는 위젯이 더 이상 사용되지 않을 때 컨트롤러를 해제하는 데 사용됩니다.
  • _sendEmail() 메서드는 이메일 전송을 처리합니다.
    • _formKey.currentState!.validate()를 사용하여 사용자 입력을 유효성 검사합니다.
    • 유효성 검사에 통과하면 Email 객체를 생성합니다.
      • body: 이메일 본문. 사용자 입력 정보와 함께 미리 정의된 텍스트를 포함합니다.
      • subject: 이메일 제목.
      • recipients: 받는 사람 이메일 주소 목록.
      • cc: CC 이메일 주소 목록 (선택사항).
      • isHTML: 이메일 본문이 HTML 형식인지 여부 (기본값: false).
    • FlutterEmailSender.send 메서드를 사용하여 이메일을 보냅니다.
      • 성공하면 이전 페이지로 돌아갑니다.
      • 실패하면 오류 메시지를 표시합니다.
  • build() 메서드는 위젯의 UI를 구성합니다.
    • AppBar를 사용하여 제목을 표시합니다.
    • Form 위젯을 사용하여 사용자 입력 필드를 구성합니다.
      • TextFormField 위젯을 사용하여 아이디, OS 버전, 기기, 문의 내용을 입력할 수 있도록 합니다.
      •  TextFormField 위젯에는 decoration 속성을 사용하여 라벨 텍스트를 설정하고 validator 속성을 사용하여 사용자 입력을 유효성 검사합니다.
    • ElevatedButton 위젯을 사용하여 "보내기" 버튼을 추가합니다.
      • onPressed 속성을 _sendEmail 메서드에 연결하여 버튼 클릭 시 이메일 전송을 처리하도록 합니다.

2. 유용한 팁

  • 사용자 입력 유효성 검사: Form 위젯과 TextFormField 위젯을 사용하여 사용자 입력을 유효성 검사하고 오류 메시지를 표시합니다.
  • 로딩 표시기: await 키워드를 사용하여 비동기 작업을 수행하는 동안 로딩 표시기를 표시합니다.
  • 다양한 이메일 주소: recipients, cc, bcc 속성을 사용하여 여러 이메일 주소로 동시에 이메일을 보낼 수 있습니다.
  • 파일 첨부: attachFile 및 attachments 속성을 사용하여 이메일에 파일을 첨부할 수 있습니다.
  • HTML 형식: isHTML 속성을 true로 설정하여 HTML 형식의 이메일 본문을 사용할 수 있습니다.
  • 사용자 정의 글꼴: customTypeface 속성을 사용하여 이메일 본문에 사용할 글꼴을 지정할 수 있습니다.

3. 고급 기능

  • 이메일 미리보기: previewEmail 메서드를 사용하여 이메일을 보내기 전에 미리보기를 표시할 수 있습니다.
  • 이메일 저장 및 관리: 사용자가 보낸 이메일을 저장하고 관리할 수 있는 시스템을 구축할 수 있습니다.
  • 템플릿 사용: 미리 정의된 템플릿을 사용하여 일반적인 문의 유형에 대한 이메일 작성을 간편하게 만들 수 있습니다.

4. 마무리

 

이 블로그 게시물을 통해 Flutter에서 flutter_email_sender 패키지를 사용하여 문의 이메일 시스템을 구축하는 방법에 대한 포괄적인 이해를 얻으셨기를 바랍니다.

코드 예시, 팁, 고급 기능을 활용하여 실제 앱에 적용하고 사용자에게 편리하고 효율적인 문의 시스템을 제공할 수 있도록 하십시오.

 

Starting Google Play App Distribution! "Tester Share" for Recruiting 20 Testers for a Closed Test.

 

Tester Share [테스터쉐어] - Google Play 앱

Tester Share로 Google Play 앱 등록을 단순화하세요.

play.google.com

 

728x90
반응형