C言語関係掲示板

過去ログ

No.1033 C言語でsmtpを使用したメール送信のプログラム

[戻る] [ホームページ]
No.13232

C言語でsmtpを使用したメール送信のプログラム
投稿者---大四郎(2004/03/18 20:42:11)




HP-UX11.00、UNIX-Cなのですが、
C言語でsmtpを使用してメールの送信を行いたいのですが、
1アドレスに対しては送信が行えるのですが、TOを複数指定
例えば、「to:yamada@test.co.jp,saitoh@test.co.jp」と
すると処理は正常に終わるのですが、送信が行われていません。

また、添付ファイルを付与して送信したいのですが、どのように
すればよいのですか。

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>

extern int errno ;

int main(argc, argv)
int argc ;
char **argv ;
{
    char c ;
    FILE *fp,*fn ;
    char hostname[64],fromname[64],toname[64],filename[64],sstrs[64],rstrs[2048] ;
    char texts[32000] ;
    char l[64] ;
    register long int i,s ;
    long int m, j, k ;
    struct hostent *hp ;
    struct sockaddr_in sin ;

    /* argc check */
    if ((argc < 4)||(argc > 5)) {
        /* print Usage */
        fprintf(stderr, " Usage: %s smtp_hostname from_name to_name text_filename\n",argv[0]) ;
        exit(-1) ;
    }

    /* set hostname */
    /* gethostname(hostname, sizeof(hostname)) ;*/
    strcpy(hostname,argv[1]) ;
    /* set fromname */
    strcpy(fromname,argv[2]) ;
    /* set toname */
    strcpy(toname,argv[3]) ;
    /* set filename */
    strcpy(filename,argv[4]) ;

    /* open send file */
    if((fn = fopen(filename,"r")) == NULL) {
        perror("cannot open file") ;
        exit(-1) ;
    }

    /* lookup the network address */
    if ((hp = gethostbyname(hostname)) == NULL) {
        fprintf(stderr, "%s: unknown host.\n", hostname) ;
        exit(-1) ;
    }

    /* get a socket to work with. */
    if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        fprintf(stderr,"client: socket error.\n") ;
        exit(-1) ;
    }

    /* create the address we will be connecting to. */
    /* use smtp port 25 */
    sin.sin_family = AF_INET ;
    sin.sin_port = htons(25) ;
    bcopy(hp->h_addr, &sin.sin_addr, hp->h_length) ;
    /* try to connect to the address. */
    if (connect(s, &sin, sizeof(sin)) < 0) {
        fprintf(stderr,"client: connect error.\n") ;
        exit(-1) ;
    }

    /* open reading the socket. */
    fp = fdopen(s, "r") ;

    /* first read some strings. */
    fgets(rstrs, 2048, fp) ;

    /* send fromname */
    strcpy(sstrs,"HELO ") ;
    strcat(sstrs,hostname) ;
    strcat(sstrs,"\r\n") ;
    send(s,sstrs,strlen(sstrs), 0) ;
    printf("Connect to:%s\n",hostname) ;

    /* read response */
    fgets(rstrs, 2048, fp) ;

    /* send fromname */
    strcpy(sstrs,"MAIL FROM:<") ;
    strcat(sstrs,fromname) ;
    strcat(sstrs,">\r\n") ;
    send(s,sstrs,strlen(sstrs), 0) ; 
    printf("Mail from:%s\n",fromname) ;

    /* read response */
    fgets(rstrs, 2048, fp) ;

    /* send toname */
    strcpy(sstrs,"RCPT TO:<") ;
    strcat(sstrs,toname) ;
    strcat(sstrs,">\r\n") ;
    send(s,sstrs,strlen(sstrs), 0) ;
    printf("Mail to:%s\n",toname) ;

    /* read response */
    fgets(rstrs, 2048, fp) ;

    /* put message ready */
    strcpy(sstrs,"DATA\r\n") ;
    send(s,sstrs,strlen(sstrs), 0) ;

    /* read response */
    fgets(rstrs, 2048, fp) ;

    /* put message */
    strcpy(sstrs,"From:") ;
    strcat(sstrs,fromname) ;
    strcat(sstrs,"\r\n") ;
    send(s,sstrs,strlen(sstrs), 0) ;
    strcpy(sstrs,"To:") ;
    strcat(sstrs,toname) ;
    strcat(sstrs,"\r\n") ;
    send(s,sstrs,strlen(sstrs), 0) ;
    strcpy(sstrs,"X-Mailer:smtpsend ") ;
    strcat(sstrs,"\r\n") ;
    send(s,sstrs,strlen(sstrs), 0) ;

    printf("---DATA Start---\n") ;
    printf("%s\n------------------------\n",sstrs) ;
  
    i = 0 ;
    while ((m = fgetc(fn)) != EOF)
        texts[i++] = m ;

    j = 0 ; k = 0 ; sstrs[0] = 0 ;
    while (texts[j] != 0) {
        if((texts[j] == 0x0A)||(texts[j] == 0x0D)){
            sstrs[k++] = 0 ;
            j++ ;
            if((texts[j] == 0x0A)||(texts[j] == 0x0D)){
                sstrs[k] = 0 ;
                j++ ;
            }
            printf("%s\n",sstrs) ;
            strcat(sstrs,"\r\n") ;
            send(s,sstrs,strlen(sstrs),0) ;
            k = 0 ; sstrs[0] = 0 ;
         } else {
             sstrs[k++] = texts[j++] ;
         }
    }
    if( k > 0){
        sstrs[k] = 0 ;
        printf("%s\n",sstrs) ;
        strcat(sstrs,"\r\n") ;
        send(s,sstrs,strlen(sstrs),0) ;
    }

    /* put message end */
    strcpy(sstrs,"\r\n.\r\n") ;
    send(s,sstrs,strlen(sstrs), 0) ;
    printf("------------------------\n") ;

    /* read response */
    fgets(rstrs, 2048, fp) ;

    /* quit smtp server*/
    strcpy(sstrs,"QUIT\r\n") ;
    send(s,sstrs,strlen(sstrs), 0) ;

    /* read response */
    fgets(rstrs, 2048, fp) ;

    close(s) ;
    fclose(fp) ;
    fclose(fn) ;

    printf("---Message Send---\n") ;

    exit(0) ;
}




No.13233

Re:C言語でsmtpを使用したメール送信のプログラム
投稿者---YuO(2004/03/18 21:34:49)


RFCはちゃんと読んだのでしょうか……。
SMTP, POP, HTTP等プロトコルに関する基本的な情報は,大抵RFCによって提供されています。


>C言語でsmtpを使用してメールの送信を行いたいのですが、
>1アドレスに対しては送信が行えるのですが、TOを複数指定
>例えば、「to:yamada@test.co.jp,saitoh@test.co.jp」と
>すると処理は正常に終わるのですが、送信が行われていません。

本当に処理は正常に終わっているのですか?
そもそも,レスポンスを読み飛ばしている時点で正常か否かを判別できないと思うのですが。

RFC 2821 - Simple Mail Transfer Protocol.をちゃんと読みましょう。
   The second step in the procedure is the RCPT command.

      RCPT TO:<forward-path> [ SP <rcpt-parameters> ] <CRLF>

   The first or only argument to this command includes a forward-path
   (normally a mailbox and domain, always surrounded by "<" and ">"
   brackets) identifying one recipient.

上記のように,一回のRCPT TOに書くことができるアドレスは一つだけです。


>また、添付ファイルを付与して送信したいのですが、どのように
>すればよいのですか。

RFC 2046 - Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types.を参考にしてください。
どっちかと言うと自分で添付ファイルを自分に送って,
送信or受信の時にmail bodyがどのようになっているかを調べた方が速い気もしますが……。


No.13234

Re:C言語でsmtpを使用したメール送信のプログラム
投稿者---大四郎(2004/03/18 23:14:08)


YuOさん
ありがとうございます。

>レスポンスを読み飛ばしている時点で正常か否かを判別できないと思うのですが。
確かに読み飛ばしています。
本来ならこことエラー検知のはずですね。



No.13235

Re:C言語でsmtpを使用したメール送信のプログラム
投稿者---大四郎(2004/03/18 23:29:42)


>上記のように,一回のRCPT TOに書くことができるアドレスは一つだけです。

おっしゃるとおりでした。
1受取人しか指定できないでね。

プログラムを送信人数分実行するか、RCPT TOを送信人数分実行するかない
ですね。
1回の送信でRCPT TOは数回実行できるのでしょうか。

No.13237

Re:C言語でsmtpを使用したメール送信のプログラム
投稿者---YuO(2004/03/18 23:59:09)


>プログラムを送信人数分実行するか、RCPT TOを送信人数分実行するかない
>ですね。
>1回の送信でRCPT TOは数回実行できるのでしょうか。

RFC 2821をちゃんと読みました?
30ページの4.1.1.3 RECIPIENT (RCPT)の最初の段落に何と書いてありました?

必要な情報をちゃんと提示したのですから,それを読むくらいのことはしてください。
特にNetworkは相手がいてこそ成り立つのですから,
規格も読まずにプログラムを書くと,相手に迷惑をかけることになりますよ。


No.13242

Re:C言語でsmtpを使用したメール送信のプログラム
投稿者---大四郎(2004/03/19 12:26:38)


ありがとうございます。
申し訳ありません。