ソケット通信を応用して、プログラムからメールを送信する。
| SMTPコマンド | 意味 | 例 |
|---|---|---|
HELO | 挨拶(自分のホスト名を通知) | HELO myhost |
MAIL FROM: | 送信元のメールアドレス | MAIL FROM:<sender@example.com> |
RCPT TO: | 宛先のメールアドレス | RCPT TO:<receiver@example.com> |
DATA | メール本文の開始 | DATA |
. | メール本文の終了 | .(ピリオドのみの行) |
QUIT | セッション終了 | QUIT |
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <netdb.h> #include <sys/socket.h> #define BUF_SIZE 4096 // サーバーにコマンドを送信し、応答を受け取って表示する void smtp_command(int sock, const char *cmd) { char buf[BUF_SIZE]; if (cmd != NULL) { send(sock, cmd, strlen(cmd), 0); printf("C: %s", cmd); } int n = recv(sock, buf, BUF_SIZE - 1, 0); if (n > 0) { buf[n] = '\0'; printf("S: %s", buf); } } // SMTPサーバーに接続する int connect_smtp(const char *host, int port) { struct hostent *h = gethostbyname(host); if (!h) { fprintf(stderr, "ホスト解決失敗\n"); return -1; } int sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { perror("socket"); return -1; } struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(port); memcpy(&addr.sin_addr.s_addr, h->h_addr, h->h_length); if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) { perror("connect"); close(sock); return -1; } return sock; }
int main(void) { const char *smtp_host = "mail.example.com"; const char *from = "alice@example.com"; const char *to = "bob@example.com"; // 1. SMTPサーバーに接続 int sock = connect_smtp(smtp_host, 25); if (sock < 0) return 1; // 2. サーバーの挨拶を受信 smtp_command(sock, NULL); // 3. SMTPセッション smtp_command(sock, "HELO mycomputer\r\n"); char cmd[BUF_SIZE]; snprintf(cmd, BUF_SIZE, "MAIL FROM:<%s>\r\n", from); smtp_command(sock, cmd); snprintf(cmd, BUF_SIZE, "RCPT TO:<%s>\r\n", to); smtp_command(sock, cmd); smtp_command(sock, "DATA\r\n"); // 4. メールヘッダと本文 snprintf(cmd, BUF_SIZE, "Subject: Test from C program\r\n" "From: %s\r\n" "To: %s\r\n" "\r\n" // 空行でヘッダ終了 "Hello!\r\n" "This mail was sent from a C program.\r\n" ".\r\n", // ピリオドのみの行で本文終了 from, to); smtp_command(sock, cmd); // 5. セッション終了 smtp_command(sock, "QUIT\r\n"); close(sock); printf("\nメール送信完了\n"); return 0; }
fgets でユーザーからメール本文を入力させる。// メール本文をキーボードから入力 printf("メール本文を入力(空行で終了):\n"); char body[BUF_SIZE] = ""; char line[256]; while (1) { fgets(line, 256, stdin); if (line[0] == '\n') break; // 空行で終了 strcat(body, line); }
// アドレス帳 const char *addressbook[] = { "user1@example.com", "user2@example.com", "user3@example.com" }; int num_addr = 3; printf("送り先を選択:\n"); for (int i = 0; i < num_addr; i++) printf(" %d: %s\n", i + 1, addressbook[i]); int choice; scanf("%d", &choice); const char *to = addressbook[choice - 1];
// テキストファイルからメール本文を読み込む FILE *fp = fopen("message.txt", "r"); if (fp == NULL) { perror("fopen"); return 1; } char body[BUF_SIZE] = ""; char line[256]; while (fgets(line, 256, fp) != NULL) strcat(body, line); fclose(fp);