PSoC 62S2 Wi-Fi BTパイオニアキットでのSMTPのメールクライアントを作成し、テスト用のSMTPサーバ「Smtp4dev」で動作確認します。。

テスト用のSMTPサーバ「Smtp4dev」のインストール

メール送信のテストのためにダミーのSMTPサーバ「Smtp4dev」を使用するため、「rnwood/smtp4dev」からWindows x64 binary standalone – Server edition「Rnwood.Smtp4dev-win-x64-3.2.0-ci20221023104.zip」をダウンロードします。

メールクライアントの作成

メールクライアント「Mail_Test」を作成します。「PSoC 62S2 Wi-Fi BTパイオニアキットを使ったTCP Client」で作成したTCP Clientをベースにして、メールクライアントの機能を追加します。

SMTP(Simple Mail Transfer Protocol)はメール送信に用いられるプロトコルで、TCPポートの 25番を用います。

  • 128行目のcy_rslt_t tcp_client_recv_handler()で、テスト用のSMTPサーバ「Smtp4dev」からのデータを受信します。
  • 155行目で受信データを表示します。TCP Clientを流用したために、このようなif文を使っています。
  • 158行目でmail_send()を呼び出し、SMTPに従ってデータをテスト用のSMTPサーバ「Smtp4dev」に送信します。
  • 11行目のcase文で、「HELO」を出力します。
  • 26行目のcase文で、「MAIL FROM」を出力します。
  • 42行目のcase文で、「RCPT TO」を出力します。
  • 58行目のcase文で、「DATA」を出力します。
  • 71行目のcase文で、メールヘッダと本文を出力し、メールの終了「.」を出力します。
  • 103行目のcase文で、「QUIT」を出力して、SMTPを終了します。

source\tcp_client.c

          ・・・・

void mail_send(cy_socket_t mail_handle, int num) {    // tomosoft

	cy_rslt_t result;
	char buf[MAX_TCP_DATA_PACKET_LENGTH];
	//uint32_t bytes_received = 0;
	uint32_t bytes_sent = 0;

	switch (num) {
	case 0:
		memset(buf, 0, sizeof(buf));

		/* HELOの送信 */
		strcpy(buf, "HELO ");
		strcat(buf, "smtp4dev");
		strcat(buf, "\n");
		printf("send: %s", buf);
		result = cy_socket_send(mail_handle, buf, strlen(buf),
				CY_SOCKET_FLAGS_NONE, &bytes_sent);
		if (result == CY_RSLT_SUCCESS) {
			//printf("Acknowledgment sent to TCP server\n");
		}
		break;

	case 1:
		memset(buf, 0, sizeof(buf));

		/* MAIL FROMの送信 */
		strcpy(buf, "MAIL FROM: ");
		strcat(buf, "<from@example.com>");
		strcat(buf, "\r\n");
		printf("send: %s", buf);

		result = cy_socket_send(mail_handle, buf, strlen(buf),
				CY_SOCKET_FLAGS_NONE, &bytes_sent);
		if (result == CY_RSLT_SUCCESS) {
			//printf("Acknowledgment sent to TCP server\n");
		}
		break;

	case 2:
		memset(buf, 0, sizeof(buf));

		/* RCPT TOの送信 */
		strcpy(buf, "RCPT TO: ");
		strcat(buf, "<to@smtp4dev>");
		strcat(buf, "\r\n");
		printf("send: %s", buf);

		result = cy_socket_send(mail_handle, buf, strlen(buf),
				CY_SOCKET_FLAGS_NONE, &bytes_sent);
		if (result == CY_RSLT_SUCCESS) {
			//printf("Acknowledgment sent to TCP server\n");
		}
		break;

	case 3:
		memset(buf, 0, sizeof(buf));

		strcpy(buf, "DATA\r\n");
		printf("send: %s", buf);

		result = cy_socket_send(mail_handle, buf, strlen(buf),
				CY_SOCKET_FLAGS_NONE, &bytes_sent);
		if (result == CY_RSLT_SUCCESS) {
			//printf("Acknowledgment sent to TCP server\n");
		}
		break;

	case 4:
		memset(buf, 0, sizeof(buf));

		strcpy(buf, "From:from@example.com");
		strcat(buf, "\r\n");
		strcat(buf, "To:to@smtp4dev");
		strcat(buf, "\r\n");
		strcat(buf, "Subject: テストメール");
		strcat(buf, "\r\n");
		strcat(buf, "\n");
		strcat(buf, "これはテストメールです");
		strcat(buf, "\r\n");
		printf("send: %s", buf);

		result = cy_socket_send(mail_handle, buf, strlen(buf),
				CY_SOCKET_FLAGS_NONE, &bytes_sent);
		if (result == CY_RSLT_SUCCESS) {
			//printf("Acknowledgment sent to TCP server\n");
		}
		
		memset(buf, 0, sizeof(buf));
		strcpy(buf, ".\r\n");

		result = cy_socket_send(mail_handle, buf, strlen(buf),
				CY_SOCKET_FLAGS_NONE, &bytes_sent);
		if (result == CY_RSLT_SUCCESS) {
			//printf("Acknowledgment sent to TCP server\n");
		}
		printf("send: %s", buf);

		break;

	case 5:
		result = cy_socket_send(mail_handle, "QUIT\r\n", strlen("QUIT\r\n"),
				CY_SOCKET_FLAGS_NONE, &bytes_sent);
		if (result == CY_RSLT_SUCCESS) {
			//printf("Acknowledgment sent to TCP server\n");
		}
		printf("send: QUIT\r\n");
		break;
	}
}

/*******************************************************************************
 * Function Name: tcp_client_recv_handler
 *******************************************************************************
 * Summary:
 *  Callback function to handle incoming TCP server messages.
 *
 * Parameters:
 *  cy_socket_t socket_handle: Connection handle for the TCP client socket
 *  void *args : Parameter passed on to the function (unused)
 *
 * Return:
 *  cy_result result: Result of the operation
 *
 *******************************************************************************/
cy_rslt_t tcp_client_recv_handler(cy_socket_t socket_handle, void *arg) {
	/* Variable to store number of bytes send to the TCP server. */
	//uint32_t bytes_sent = 0;

	/* Variable to store number of bytes received. */
	uint32_t bytes_received = 0;

	char message_buffer[MAX_TCP_DATA_PACKET_LENGTH];
	cy_rslt_t result;

	// printf("============================================================\n");
	memset(message_buffer, 0, sizeof(message_buffer));

	result = cy_socket_recv(socket_handle, message_buffer, TCP_LED_CMD_LEN,
			CY_SOCKET_FLAGS_NONE, &bytes_received);

	if (message_buffer[0] == LED_ON_CMD) {
		/* Turn the LED ON. */
		cyhal_gpio_write(CYBSP_USER_LED, CYBSP_LED_STATE_ON);
		printf("LED turned ON\n");
		sprintf(message_buffer, ACK_LED_ON);
	} else if (message_buffer[0] == LED_OFF_CMD) {
		/* Turn the LED OFF. */
		cyhal_gpio_write(CYBSP_USER_LED, CYBSP_LED_STATE_OFF);
		printf("LED turned OFF\n");
		sprintf(message_buffer, ACK_LED_OFF);
	} else {
		printf("rcv  %s", message_buffer);
		sprintf(message_buffer, MSG_INVALID_CMD);
	}
	mail_send(socket_handle, recv_count);
	recv_count++;
	if (recv_count >= 6) {
		recv_count = 0;
	}
	/* Send acknowledgment to the TCP server in receipt of the message received. 
	 result = cy_socket_send(socket_handle, message_buffer,
	 strlen(message_buffer), CY_SOCKET_FLAGS_NONE, &bytes_sent);
	 if (result == CY_RSLT_SUCCESS) {
	 printf("Acknowledgment sent to TCP server\n");
	 }
	 */
	return result;
}
          ・・・・


メールクライアントの実行

作成したメールクライアント「Mail_Test」を実行し、メールサーバ「Smtp4dev」を使用してメールを送信します。

  1. インストールしたメールサーバ「Smtp4dev」の「・・・Rnwood.Smtp4dev-win-x64-3.2.0-ci20221023104\Rnwood.Smtp4dev.exe」を実行します。
  2. TeraTermを起動すると、TeraTermには次のようにSMTPプロトコルの実行ログが表示されます。
  3. メールサーバ「Smtp4dev」のログが「http://localhost:5000」に表示されます。「Messages」タブには次のように表示されます。
  4. メールサーバ「Smtp4dev」のログが「http://localhost:5000」に表示されます。「Sessions」タブには次のように表示されます。