Javamailを学んだので応用してお問い合わせフォームっぽいのをつくってみた

こんにちはandroidでアプリ開発を学習中のみのむしと申します。
今回は、Javamailを勉強したため応用してお問い合わせフォームっぽいのを作ってみました。

仕組みとしては、送信元アドレスと送信先アドレスを設定し、
一度メールを送信したら以降はメールの本文の中に記載したユーザーのアドレス
と送信先アドレス間でやり取りを行うイメージです。

<h2>gmailの設定等</h2>

今回はSMTP通信を使って実装していきます。

また、以前までは、gmail内にある「セキュリティ > 安全性の低いアプリのアクセス」を有効にする設定を行うことでSMTP通信が可能でしたが、2022年5月30日より、ユーザー名とパスワードのみでGoogleアカウントにログインするサードパーティ製のアプリとデバイスについてサポートが終了してしまったため、こちらの方法が使えなくなってしまいました。

そのため、今回は以下のサイトを参考にしながらアプリパスワードを発行し、SMTP通信を許可していきます。
https://itblogdsi.blog.fc2.com/blog-entry-470.html

<h2>gradleにJavaMailが使えるように必要な記述を行う</h2>
Appのbuild.gradleに下記を加える

```java
packagingOptions {
        exclude 'META-INF/NOTICE.md'
        exclude 'META-INF/LICENSE.md'
    }


dependencies {
implementation 'com.sun.mail:android-mail:1.6.6'
implementation 'com.sun.mail:android-activation:1.6.7'
}
```
<h2>パーミッションの追加</h2>
AndroidManifest.xmlにインターネット通信を許可するパーミッションを追加する

```xml
<uses-permission android:name="android.permission.INTERNET" />
```
<h2>strings.xmlに以下の記述を行う</h2>

```xml
    <string name="contact">お問い合わせ</string>
    <string name="contact_US">contact</string>
    <string name="contact_text">本アプリに関するご質問・ご要望・不具合等のご連絡\nにつきましては下記より必要事項をご記入の上ご連絡\nください。</string>
    <string name="Name">Name</string>
    <string name="Email">E_mail</string>
    <string name="message">Message</string>
    <string name="send">Send</string>
```


<h2>activity_main.xmlに以下の記述を行う</h2>

※画像はお好みの画像を入れて下さい

```xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white"
    tools:context=".MainActivity">

    <androidx.cardview.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="16dp"
        android:layout_marginRight="8dp"
        android:layout_marginBottom="16dp"
        app:cardCornerRadius="10dp"
        app:cardElevation="3dp">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <ImageView
                android:id="@+id/Header_Image"
                android:layout_width="wrap_content"
                android:layout_height="150dp"
                android:scaleType="centerCrop"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:srcCompat="@drawable/contact"
                tools:ignore="ContentDescription" />

            <TextView
                android:id="@+id/contact_us"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/contact_US"
                android:textColor="@color/black"
                android:textSize="35sp"
                android:layout_marginTop="40dp"
                android:textStyle="italic"
                android:typeface="serif"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/Header_Image" />

            <TextView
                android:id="@+id/contact_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="15dp"
                android:padding="10dp"
                android:text="@string/contact_text"
                android:textColor="@color/black"
                android:textSize="15sp"
                android:textStyle="italic"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/contact_us" />

            <com.google.android.material.textfield.TextInputLayout
                android:id="@+id/name_layout"
                android:layout_width="174dp"
                android:layout_height="55dp"
                android:layout_marginStart="20dp"
                android:layout_marginTop="35dp"
                android:layout_marginEnd="10dp"
                app:boxStrokeColor="@color/black"
                app:hintTextColor="@color/black"
                app:layout_constraintEnd_toStartOf="@+id/Email_layout"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/contact_text">

                <com.google.android.material.textfield.TextInputEditText
                    android:id="@+id/NameText"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:hint="@string/Name"
                    android:singleLine="true"
                    android:textStyle="bold|italic" />

            </com.google.android.material.textfield.TextInputLayout>

            <com.google.android.material.textfield.TextInputLayout
                android:id="@+id/Email_layout"
                android:layout_width="174dp"
                android:layout_height="55dp"
                android:layout_marginStart="10dp"
                android:layout_marginTop="35dp"
                android:layout_marginEnd="20dp"
                app:boxStrokeColor="@color/black"
                app:hintTextColor="@color/black"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toEndOf="@+id/name_layout"
                app:layout_constraintTop_toBottomOf="@+id/contact_text">

                <com.google.android.material.textfield.TextInputEditText
                    android:id="@+id/EmailText"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:hint="@string/Email"
                    android:singleLine="true"
                    android:textStyle="bold|italic" />

            </com.google.android.material.textfield.TextInputLayout>

            <com.google.android.material.textfield.TextInputLayout
                android:id="@+id/Massage_layout"
                android:layout_width="368dp"
                android:layout_height="87dp"
                android:layout_marginStart="8dp"
                android:layout_marginTop="50dp"
                android:layout_marginEnd="8dp"
                app:boxStrokeColor="@color/black"
                app:hintTextColor="@color/black"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/name_layout">

                <com.google.android.material.textfield.TextInputEditText
                    android:id="@+id/MessageText"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:hint="@string/message"
                    android:textStyle="bold|italic"
                    />

            </com.google.android.material.textfield.TextInputLayout>

            <com.google.android.material.button.MaterialButton
                android:id="@+id/Send_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="30dp"
                android:backgroundTint="@color/black"
                android:text="@string/send"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/Massage_layout" />

        </androidx.constraintlayout.widget.ConstraintLayout>
    </androidx.cardview.widget.CardView>
</LinearLayout>


```

<h2>MainActivity内に以下の記述を行う</h2>

```java

import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import com.google.android.material.button.MaterialButton;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

public class MainActivity extends AppCompatActivity {
    EditText mName;
    EditText M_email;
    EditText M_message;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //アクションバーを非表示にする設定
        ActionBar actionBar = getSupportActionBar();
        if(actionBar != null){
            actionBar.hide();
        }

        //送信ボタンを取得する
        MaterialButton SendButton = findViewById(R.id.Send_button);
        SendButton.setOnClickListener(new SendButtonOnClick());

        //各種EditTextを取得する
        mName = findViewById(R.id.NameText);
        M_email = findViewById(R.id.EmailText);
        M_message = findViewById(R.id.MessageText);

    }

    //送信ボタンを押したときに起動するリスナクラス
    private class SendButtonOnClick implements View.OnClickListener{

        @Override
        public void onClick(View view) {
            buttonSendEmail();
        }
    }

    private void buttonSendEmail() {
        try {
            //送信元アドレスを設定する
            String sender_Email = "ほげほげ@gmail.com";
            //送信元内で作成したアプリパスワードを設定する
            String sender_password = "作成した上記gmailアドレスのアプリパスワード";
            //送信先アドレスを設定する
            String ReceiverEmail = "送信先のメールアドレス";
            
            String Hostname = "smtp.gmail.com";
            Properties properties = System.getProperties();

            //使用するポート番号と認証方式を入力する
            properties.put("mail.smtp.host", Hostname);
            properties.put("mail.smtp.port", "587");
            properties.put("mail.smtp.starttls.enable", "true");
            properties.put("mail.debug", "true");
            properties.put("mail.smtp.auth", "true");

            //sessionを取得する
            final javax.mail.Session session = Session.getInstance(properties, new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(sender_Email, sender_password);
                }
            });

            //MimeMessage内に作成したsessionと送信先の情報を設定する
            MimeMessage mimeMessage = new MimeMessage(session);
            mimeMessage.addRecipient(Message.RecipientType.TO, new InternetAddress(ReceiverEmail));

            //件名を記載する
            mimeMessage.setSubject("テストメール");

            //本文を設定する
             mimeMessage.setText(("お客様お名前" +  System.getProperty("line.separator")
                    + mName.getText() + System.getProperty("line.separator")+ System.getProperty("line.separator")
                    + "お客様のメールアドレス" + System.getProperty("line.separator") + M_email.getText())
                    + System.getProperty("line.separator") + System.getProperty("line.separator")
                    + "お問い合わせ内容" + System.getProperty("line.separator") + M_message.getText());

            Thread thread = new Thread(() -> {
                try {
                    Transport.send(mimeMessage);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });

            thread.start();
            Log.d("送信", "送信完了です");
            onPostExecute();
            remove();

        }catch (AddressException e) {
            Log.e("Error", "AddressException");
            e.printStackTrace();

        } catch (MessagingException e) {
            Log.e("Error", "MessagingException");
            e.printStackTrace();

        }

    }

    protected void onPostExecute() {
        //画面にメッセージを表示させる
        Toast.makeText(MainActivity.this, (String) "送信が完了しました", Toast.LENGTH_LONG).show();

    }

    //メールの送信が完了したらテキストを空にする処理
    protected void remove() {
        M_message.setText("");
        mName.setText("");
        M_email.setText("");
    }
}
```

<h2>実行結果</h2>

「送信」ボタンをタップすると、メールが送信され画面にトーストが表示されます。

![image1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523916/5a6e7345-c2f9-66b2-cf07-16364c2a88b0.png)

<h2>正常に受信した場合</h2>

![image2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523916/19feeddf-46aa-8e48-daf3-b56877f4b83d.png)

<h2>参考サイト</h2>

https://qiita.com/Rabbit_Program/items/9df03bf2c1885561a5bd
https://qiita.com/nozaki-sankosc/items/3f52c011ffd5db546763
https://www.shookuro.com/entry/java-mail-gmail