-
[Android/Java] Javax로 Email 보내기Coding/Android 2019. 11. 13. 14:31
Javax.mail 사용해보기
안녕하세요 오늘은 자바의 라이브러리 중 하나인 javax를 이용하여 이메일을 보내보겠습니다.
javax의 mail, activation, additionnal 라이브러리가 필요한데, 이는 import error가 자주 발생합니다.
(클래스가 코드상에서는 찾지만, 빌드 시에 앱에서는 찾지 못하는 에러가 발생합니다)
따라서 라이브러리를 수동으로 추가해 주어야 합니다. (이전 포스팅 참고)
우선 https://code.google.com/archive/p/javamail-android/downloads에서 라이브러리를 받아와서
프로젝트의 /app/libs에 넣어주고 수동으로 라이브러리를 추가해줍니다(이전 포스팅 참고)
이메일을 보내기 위해서는 Internet Permission이 필요합니다.
Manifest에 다음과 같이 추가해주세요.
<uses-permission android:name="android.permission.INTERNET" />
저는 해당 코드를 안드로이드에서 작성하였기 때문에 새로 클래스 파일을 만들어 주겠습니다.
새로 클래스를 만들어 GMailSender.java를 작성하겠습니다.
GMailSender.java
import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Properties; import javax.activation.DataHandler; import javax.activation.DataSource; import javax.mail.Message; import javax.mail.PasswordAuthentication; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; public class GMailSender extends javax.mail.Authenticator { private String mailhost = "smtp.gmail.com"; private String user; private String password; private Session session; private String emailCode; public GMailSender(String user, String password) { this.user = user; this.password = password; emailCode = createEmailCode(); Properties props = new Properties(); props.setProperty("mail.transport.protocol", "smtp"); props.setProperty("mail.host", mailhost); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.port", "465"); props.put("mail.smtp.socketFactory.port", "465"); props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); props.put("mail.smtp.socketFactory.fallback", "false"); props.setProperty("mail.smtp.quitwait", "false"); //구글에서 지원하는 smtp 정보를 받아와 MimeMessage 객체에 전달해준다. session = Session.getDefaultInstance(props, this); } public String getEmailCode() { return emailCode; } //생성된 이메일 인증코드 반환 private String createEmailCode() { //이메일 인증코드 생성 String[] str = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "1", "2", "3", "4", "5", "6", "7", "8", "9"}; String newCode = new String(); for (int x = 0; x < 8; x++) { int random = (int) (Math.random() * str.length); newCode += str[random]; } return newCode; } protected PasswordAuthentication getPasswordAuthentication() { //해당 메서드에서 사용자의 계정(id & password)을 받아 인증받으며 인증 실패시 기본값으로 반환됨. return new PasswordAuthentication(user, password); } public synchronized void sendMail(String subject, String body, String recipients) throws Exception { MimeMessage message = new MimeMessage(session); DataHandler handler = new DataHandler(new ByteArrayDataSource(body.getBytes(), "text/plain")); //본문 내용을 byte단위로 쪼개어 전달 message.setSender(new InternetAddress(user)); //본인 이메일 설정 message.setSubject(subject); //해당 이메일의 본문 설정 message.setDataHandler(handler); if (recipients.indexOf(',') > 0) message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipients)); else message.setRecipient(Message.RecipientType.TO, new InternetAddress(recipients)); Transport.send(message); //메시지 전달 } public class ByteArrayDataSource implements DataSource { private byte[] data; private String type; public ByteArrayDataSource(byte[] data, String type) { super(); this.data = data; this.type = type; } public ByteArrayDataSource(byte[] data) { super(); this.data = data; } public void setType(String type) { this.type = type; } public String getContentType() { if (type == null) return "application/octet-stream"; else return type; } public InputStream getInputStream() throws IOException { return new ByteArrayInputStream(data); } public String getName() { return "ByteArrayDataSource"; } public OutputStream getOutputStream() throws IOException { throw new IOException("Not Supported"); } } }
코드가 난해해 보이지만, smtp 연결과 포트 구성을 위한 코드로 그저 복붙 해주시면 됩니다.
그다음에 SendMail이라는 클래스를 만들어봅시다.
SendMail.java
import android.content.Context; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import javax.mail.MessagingException; import javax.mail.SendFailedException; public class SendMail extends AppCompatActivity { String user = user; // 보내는 계정의 id String password = password; // 보내는 계정의 pw public void sendSecurityCode(Context context, String sendTo) { try { GMailSender gMailSender = new GMailSender(user, password); gMailSender.sendMail("제목입니다", "내용입니다", sendTo); Toast.makeText(context, "이메일을 성공적으로 보냈습니다.", Toast.LENGTH_SHORT).show(); } catch (SendFailedException e) { Toast.makeText(context, "이메일 형식이 잘못되었습니다.", Toast.LENGTH_SHORT).show(); } catch (MessagingException e) { Toast.makeText(context, "인터넷 연결을 확인해주십시오", Toast.LENGTH_SHORT).show(); } catch (Exception e) { e.printStackTrace(); } } }
이제 MainActivity에서 SendMail 객체를 생성하면서 생성자를 통해, 보내는 계정의 id와 pw를 전달하여 메일을 보낼수 있게 됩니다.
메일을 보내는 주체가 하나라면 다음과 같이 코딩해도 되지만, 여러 개의 객체를 만들어 사용할 거라면, 생성자를 통해 전달을 하는게 더 바람직하겠죠?
저 같은 경우, noreply 계정 하나에서만 메일을 보내게 할 것이기 때문에 굳이 생성자로 전달을 하지는 않겠습니다.
GmailSender의 sendMail 메소드는, 위에서 작성하지는 않았지만 javax.mail.Authenticator을 상속받으면서 사용할 수 있게 되는 메소드로, 매개변수로 메일의 제목과 내용, 받는 계정(이메일)을 지정합니다. 이제 MainAcitivity에서 이 받는 계정을 매개변수로 전달해주면 해당 제목과 내용의 메일이 전송될 것입니다.
이제 MainActivity에서 만든 sendSecurityCode() 를 호출해 봅시다.
MainActivity.java
package com.example.asky; import android.os.Bundle; import android.os.StrictMode; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { Button mailButton = null; EditText emailText = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() .permitDiskReads() .permitDiskWrites() .permitNetwork().build()); mailButton = (Button) findViewById(R.id.mailButton); emailText = (EditText) findViewById(R.id.emailTextView); mailButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v){ SendMail mailServer = new SendMail(); mailServer.sendSecurityCode(getApplicationContext(), emailText.getText().toString()); } }); } }
SendMail 클래스의 sendSecurityCode()에서 sendTo라는 String을 매개변수로 전달하였습니다.
이 sendTo가 받는 계정의 이메일을 전달해 주면 되겠습니다.
MainActivity에서는 TextView로부터 받는 계정의 이메일을 전달받아, Button을 누르면 해당 이메일로 메일이 전송되는
형태입니다. 한번 실제로 확인해 볼까요?
이메일을 성공적으로 보냈습니다, 라는 토스트 메시지가 튀어나오면 정상적으로 메일이 보내진 것이고,
확인해보니 메일이 제대로 와있네요!
이상으로 포스팅을 마칩니다.
'Coding > Android' 카테고리의 다른 글
[Android] javax.mail Import 에러 해결법 (0) 2019.11.12 Adb device 무선(Wifi)로 연결하기 (0) 2019.11.07 [안드로이드 스튜디오] TODO를 이용하여 효율적으로 개발하기 (0) 2019.08.06 [안드로이드 - 코틀린] 센서 값 Delay 속도 지정하기 (0) 2019.08.06 [안드로이드 - 코틀린] 지연된 초기화(by lazy) (0) 2019.08.06