• 締切済み

ソケット通信で大容量のメールの場合送信されません

質問です smtpクライアントからtcpでメール送信するプログラムを組んだのですが、 添付ファイルのサイズが大きいもの(500000行を超えるような)を1行ずつsendメソッドで送信すると送信先で受信できません。 400000行まではいくのですが… sendではエラーは返っておらずパケットは送られてる様です。 パケットダンプをとってみたのですが、メールサーバから応答は返ってきていました。 filein.open("test.eml"); if (filein.fail()){ return -1; } if((soc = ConnectHost("testhost","smtp",25)) == -1){ return -1; } send_buf = new char[BUFSIZ]; sprintf(send_buf,"MAIL FROM:<%s>\r\n","test@test.test"); SocketSend(soc,send_buf,strlen(send_buf)); sprintf(send_buf,"RCPT TO:<%s>\r\n","test2@test.test"); SocketSend(soc,send_buf,strlen(send_buf)); sprintf(send_buf,"DATA\r\n"); SocketSend(soc,send_buf,strlen(send_buf)); ss = new char[1024]; while (filein.getline(ss,1024)){ sprintf(send_buf,"%s\r\n",ss); SocketSend(soc,send_buf,strlen(send_buf)); ←ここでループ } delete ss; sprintf(send_buf,"\r\n.\r\n"); SocketSend(soc,send_buf,strlen(send_buf)); SocketRead(soc,send_buf); delete send_buf; filein.close(); if(SocketClose(soc) == -1){ return err; } int SocketSend(int soc,char* buff,int nbytes) { register int nleft,nwritten; char* p = buff; nleft = nbytes; while(nleft > 0) { nwritten = send(soc,p,nleft,0); if(nwritten <= 0){ return nwritten; } nleft -= nwritten; p += nwritten; } return 0; } int SocketClose(int soc) { int ret; if(close(soc) == -1){ return -1; } return 0; } int SocketRead(int soc,char* buff) { int rbyte; rbyte = read(soc,buff,strlen(buff)); return 0; } 上記で問題になっていそうなところがあれば 教えてください。。 よろしくお願いします。

みんなの回答

  • chie65535
  • ベストアンサー率43% (8520/19369)
回答No.1

>添付ファイルのサイズが大きいもの(500000行を超えるような)を1行ずつsendメソッドで送信すると送信先で受信できません。 メールにはISPにより「最大行数」または「最大サイズ」に制限があります。 とあるISPでは5MB、とあるISPでは1MB、とあるISPでは30万行と、ISPごとに「最大値」はバラバラです。また、一部のISPでは最大値を設けていない場合もあります。 また、メールを受信するサーバーに制限が無くとも、中継するサーバーに制限がある場合もあり「送れるかどうかは、実際に送ってみないと判らない」というのが現状です。

okuraman
質問者

お礼

ご回答ありがとうございます。 ご回答頂いた点ですが、 phpのプログラムからは正常に送れていますので サーバ側に問題はないと考えています。

関連するQ&A

  • ネットワーク初心者です。

    ネットワーク初心者です。 borland C++でプログラム作成しているのですが、windowsクライアントからサーバーに対してソケットを生成して(c言語)、ファイルをhttp通信で送信したいんですが、うまくいきません。とりあえず、ソケット生成とサーバーcgiプログラムを呼び出すことは出来たんですが、それに対してhttpでファイルを送信するには、どうすればいいのでしょうか? 誰か、ご教授願えますか? ちなみに、サーバーcgi呼び出したのは、 sprintf(send_buf, "POST %s http/1.0\r\n\r", path); send(s, send_buf, strlen(send_buf),0); sprintf(send_buf, "Host: %s:%d\r\n", host, port); send(s, send_buf, strlen(send_buf), 0); sprintf(send_buf, "\r\n"); send(s, send_buf, strlen(send_buf), 0); です。

  • smtp-auth でメール送信

    補足します。  認証終了後、 MAIL FROM を送ります。 sprintf (out_data, "MAIL FROM:<%s>\r\n", buf); if ( 0!=put_smtp_auth_line( SMTPSock, out_data, strlen (out_data) ) ) return(-1); buf には、自分のメールアドレスが入っています。 この結果は、 500 5.5.1 Command unrecognized: "" が帰ってきます。

  • 配列内に通番(文字列)を挿入したいのですが・・・(Winsock利用)

    こんばんわ。 A端末(送信端末)→B端末(受信端末)というように、A端末から複数パケットを送信し、B端末でパケットを受信するというプログラムをUDPを用いて作成しています。 [実装したいこと] ・A端末において各パケットに対して、通番(TCPのシーケンス番号)のよ うなものを挿入し、パケットを送出。 ・B端末で、どの通番を持つパケットを受信することができたか?を確 認したい。 と思っています。 そこで、上記をふまえ以下のようなプログラムを作成しました。 [A端末(送信側)] //main main(int argc ,char *argv[]){   UDPSending(s_port,szServer); } //whileループにてsend_packet関数を何回も呼び出す。packet_Num変数よりカウントアップ。 UDPSending(unsigned short s_port,char *szServer){  int packet_Num = 1;   while((n = fread(send_Buf,1,SEND_DATA_SIZE,fp)) != 0) {    send_packet(packet_Num, s_port, szServer, send_Buf, n);    packet_Num++;  } } //sprintf関数を使用し各パケットに通番を付加 send_packet(int packet_Num, unsigned short s_port, char *szServer, char *send_Buf, int n){   char send_Buff[1500];   //配列初期化   memset(send_Buff,'\0',sizeof(send_Buff));   //send_Bufに文字列を付加?   sprintf(send_Buf+32,"%d\n",packet_Num);   //send_Bufの内容をsend_Buffへコピー   memcpy(send_Buff,send_Buf,n);   UDPDataSend(s_port, szServer, send_Buff, n); } //パケット送出 UDPDataSend(unsigned short s_port, char *szServer, char *send_Buff, int n){   sendto(省略) } 上記のように、sprintf関数を使用しpacket_Num変数の文字列を挿入することで、送出されるパケットに通番を割り振っていることになるのでしょうか? よろしくお願い致します。

  • 通信(送信)のプログラム

    bool WriteData(char *buff, unsigned int data_size) {     DWORD dwWritten; /* ポートへ書き込んだバイト数 */ WriteFile(hComm, buff, data_size, &dwWritten, NULL); if (dwWritten!=data_size) { printf("データの送信に失敗しました。\n"); return false; } return true; } 上の関数はシリアル通信の送信する関数なんですが、これに数値などを入れたいんですが、char型のため、一文字しか入れれません。たとえば、01ならchar型の0とchar型の1を別々に送らないとだめなんですが、このようにするしか無理なんでしょうか?int型の数値を好きなように入れて送りたいんですが。あと、OxFFのように16進数も入れれると便利なんですが。駄文ですいません。プログラムの知識が浅はかですいません。

  • Winsockを用いてデータを交互に送信しあいたい

    チャットプログラムではないのですが、チャットプログラムのソースが参考になると思いネットで調べて見ましたが見つからなかったので質問させていただきます。 したいのは、.rarなどの圧縮されたファイル(サイズはGB単位)の送信(TCP)です。 トータルのファイルサイズとファイル名をBYTE配列に書き込む BYTE配列のサイズを送信後、BYTE配列を送信 (とりあえずここでトータルサイズを4MB(4×1024×1024)で割った商をQ、余りをRと置いておく) ファイルをバイナリ読み込みモードで開く 受け取ったという合図を受け取ったらファイルの先頭から4MB読み込んでBYTE配列に入れて送信 受け取ったという合図を受け取ったら続きから4MB読み込んでBYTE配列に入れて送信 ↑を先頭の分も合わせてQ回繰り返す。 受け取ったという合図を受け取ったら続きからRバイト読み込んでBYTE配列に入れて送信 ファイルを閉じる としたのですが、 ファイルの先頭から4MBは送信できているようなのですが、そこから先に進みません。 具体的には、4MBの受信したという合図を送っても、send関数が-1を返すようです プログラムは以下の通りです Server Winsockの設定やファイルのトータルサイズ云々なので略 listen( RecvSock, 5 ); fp = fopen( FileName, "rb" ); int TotalSend = 0; int i = -1; SendSock = accept(RecvSock, (struct sockaddr *)&Send, &len);//コメントアウトを外す場合はこれはコメントアウト while(1) { //SendSock = accept(RecvSock, (struct sockaddr *)&Send, &len); if( i == -1 ) { send( SendSock, (char *)&FileSize, 4, 0 ); //↓の配列サイズを入れたBYTE配列 send( SendSock, (char *)Buff, Size, 0 );//トータルファイルサイズとファイル名 delete []Buff;//BYTE *Buff = new BYTE[FileSize]としたため } //フラグ受信 { recv( SendSock, (char *)&i, 4, 0 ); } if( i == Q ) { fread( SendBuff, R, 1, fp ); while( TotalSend < R ) { TotalSend += send( SendSock, (char *)&SendBuff[TotalSend], R-TotalSend, 0 ); } } else if( i != -1 ) { fread( SendBuff, SendSize, 1, fp );// SendSizeは4*1024*1024の値を#define while( TotalSend < SendSize ) { TotalSend += send( SendSock, (char *)&SendBuff[TotalSend], SendSize-TotalSend, 0 ); } } printf( "%d/%d\n", i, Q ); } Client //Winsockの設定やファイルのトータルサイズ云々なので略 FILE *fp = fopen( FileName, "ab" ); int Total = 0; for( int i=0 ; i<=Q ; i++ ) { //connect( Sock, (struct sockaddr *)&Addr, sizeof(Addr) ); int Error = FileRecv( Sock, i, Q, R, fp ); if( Error == -1 ) { i--;//エラーが出るのでどこでエラーが出るのか見るために追加 } else { printf( "%d/%d\n", i, Q ); } } int FileRecv( SOCKET Sock, int Flag, int Q, int R, FILE *fp ) { //Winsockの設定をコメントアウト中。外した場合、引数のSOCKET Sockは消す int Total = 0; //フラグ送信 { BYTE buff[4]; memmove( buff, &Flag, 4 ); int Error = send( Sock, (char *)buff, 4, 0 ); if( Error == -1) { return -1; } } if( Flag == Q ){ Buff = new BYTE[R]; memset( Buff, 0, sizeof(Buff) ); while( Total < R ) { Total += recv( Sock, (char *)&Buff[Total], R-Total, 0 ); } fwrite( Buff, R, 1, fp ); delete []Buff; } else { Buff = new BYTE[SendSize]; memset( Buff, 0, sizeof(Buff) ); while( Total < SendSize ) { Total += recv( Sock, (char *)&Buff[Total], SendSize-Total, 0 ); if( Total == -1 ) { delete []Buff; return -1; } } fwrite( Buff, SendSize, 1, fp ); delete []Buff; } // closesocket(Sock); // WSACleanup(); return 1; } 毎回切断してもう一度接続しなおすようにしても(コメントアウトを外す)結果(エラー部)は変わりません。 どこが悪いのか見ていただけないでしょうか?

  • HTTPクライアントの作成について

    下のc言語で書かれたプログラムソースは、とあるHPにあったものです。受信して表示するだけですが、実際にコンパイルもでき動作も確認しています。仕組みも大体は理解しているつもりです。このプログラムを改造して、リンクのURLの一覧のみ表示させるには、どのように改造すればよいのでしょうか?それとも、根本的に仕組みが異なるのでしょうか?詳しくご指導いただけるとありがたいです。そのHPのURLものせておきます。よろしくお願いします。 URL:http://x68000.q-e-d.net/~68user/net/c-http-1.html ※includeは省略しています。 #define BUF_LEN 256 /*バッファのサイズ */ int main(int argc, char *argv[]){ int s; /*ソケットのためのファイルディスクリプタ */ struct hostent *servhost; /*ホスト名と IP アドレスを扱うための構造体 */ struct sockaddr_in server; /*ソケットを扱うための構造体 */ struct servent *service; /*サービス (http など) を扱うための構造体 */ char send_buf[BUF_LEN]; /* サーバに送るHTTP プロトコル用バッファ */ char host[BUF_LEN] = "localhost"; /*接続するホスト名 */ char path[BUF_LEN] = "/"; /*要求するパス */ unsigned short port = 0; /*接続するポート番号 */ if ( argc > 1 ){ /*URLが指定されていたら */ char host_path[BUF_LEN]; if ( strlen(argv[1]) > BUF_LEN -1 ){ fprintf(stderr, "URL が長すぎます。\n"); return 1; } /*http:// から始まる文字列で */ /*sscanf が成功して */ /*http:// の後に何か文字列が存在するなら */ if ( strstr(argv[1], "http://") && sscanf(argv[1], "http://%s", h ost_path) && strcmp(argv[1], "http://") ){ char *p; p = strchr(host_path, '/'); /* ホストとパスの区切り "/" を調べる */ if ( p != NULL ){ strcpy(path, p);/*"/"以降の文字列を path にコピー */ *p = '\0'; strcpy(host, host_path ); /*"/"より前の文字列を host にコピー */ } else {/*"/"がないなら=http://host という引数なら */ strcpy(host, host_path); /*文字列全体を host にコピー */ } p = strchr(host, ':'); /*ホスト名の部分に ":" が含まれていたら */ if ( p != NULL ){ port = atoi(p+1); /*ポート番号を取得 */ if ( port <= 0 ){ /*数字でない (atoi が失敗)か、0だったら */ port = 80; /*ポート番号は 80 に決め打ち */ } *p = '\0'; } } else { fprintf(stderr, "URLはhttp://host/path の形式で指定してください。\n"); return 1; } } printf("http://%s%s を取得します。\n\n",host, path); /* ホストの情報(IPアドレスなど)を取得 */ servhost = gethostbyname(host); if ( servhost == NULL ){ fprintf(stderr, "[%s] から IPアドレスへの変換に失敗しました。\n", host); return 0; } bzero(&server, sizeof(server));  /* 構造体をゼロクリア */ server.sin_family = AF_INET; /* IPアドレスを示す構造体をコピー */ bcopy(servhost->h_addr, &server.sin_add r,servhost->h_length); if ( port != 0 ){/* 引数でポート番号が指定されていたら */ server.sin_port = htons(port); } else {/* そうでないなら getservbyname でポート番号を取得 */ service = getservbyname("http", "tcp"); if ( service != NULL ){  /* 成功したらポート番号をコピー */ server.sin_port = service->s_port; } else { /* 失敗したら 80 番に決め打ち */ server.sin_port = htons(80); } } /* ソケット生成 */ if ( ( s = socket(AF_INET, SOCK_STREAM, 0) ) < 0 ){ fprintf(stderr, "ソケットの生成に失敗しました。\n"); return 1; } /* サーバに接続 */ if ( connect(s, (struct sockaddr *)&ser ver, sizeof(server)) == -1 ){ fprintf(stderr, "connectに失敗しました。\n"); return 1; } /* HTTP プロトコル生成 & サーバに送信 */ sprintf(send_buf, "GET %s HTTP/1.0\r\n" , path); write(s, send_buf, strlen(send_buf)); sprintf(send_buf, "Host: %s:%d\r\n", ho st, port); write(s, send_buf, strlen(send_buf)); sprintf(send_buf, "\r\n"); write(s, send_buf, strlen(send_buf)); /* あとは受信して、表示するだけ */ while (1){ char buf[BUF_LEN]; int read_size; read_size = read(s, buf, BUF_LEN); if ( read_size > 0 ){ write(1, buf, read_size); } else { break; } } /* 後始末 */ close(s); return 0; }

  • 配列とポインタについて

    こんばんわ。 WinSockを利用してネットワークプログラミングを行っています。 以下のようなプログラムを作成したのですが、実行できません。 以下のプログラムは質問箇所を抜き出したものです。 [プログラム] int Receive(u_short portNo) { char recv_Buf[1025],recv_Buff[1025]; size = recvfrom(s2, recv_Buf, (int)sizeof(recv_Buf) - 1, 0, (SOCKADDR *)&from, &fromlen); recv_Buff = recv_Buf; Sender(portNo,szServer,recv_Buff); } int Send(unsigned short portNo,char *szServer,char *recv_Buff) { sendto(s1, recv_Buff, (int)strlen(recv_Buff), 0, (LPSOCKADDR)&addrin1, sizeof(addrin1)); } このプログラムは、Receive関数内のrecvfrom関数で1024Byte(recv_Buf[1025])受信したデータをSend関数内のsendto関数で送信するというプログラムです。 recv_Buf = recv_Buffにてエラーが発生します。なにか解決策はりますでしょうか? また、Receive関数およびSend関数は何回も呼ばれるのですが、配列は初期化する必要があるのでしょうか? よろしくお願いします。

  • TCP/IP通信型大文字・小文字変換プログラム

    TCP/IP通信型大文字・小文字変換プログラムを作りたいです。 しかし、うまく2つのプログラムが接続されません。 恐らく、IPアドレスやホスト名の問題だと思います。 超初心者でそこのところをあまり理解していません。 どなたかプログラムの補足をお願いします。 概要は ・クライアント キーボードから文字列を入力し、サーバーに送信。 サーバーから送信された文字列を画面に出力。 ・サーバー クライアントから送信された文字列に対し、 大文字は小文字に、小文字は大文字に変換して返す。 クライアント側プログラム #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #define SOCK_NAME "./socket" int main() { struct sockaddr_in saddr; int soc; char buf[1024]; if ( (soc =socket(AF_INET, SOCK_STREAM, 0 ) ) < 0 ) { perror("socket"); exit(1); } memset((char *)&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr=inet_addr("192.168.1.1"); saddr.sin_port=htons(1357); if(connect(soc, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { perror("connect"); exit(1); } fprintf(stderr, "Connection established: socket %d used.\n", soc); while(fgets(buf, 1024, stdin)){ if(buf[strlen(buf) -1] == "\n") buf[strlen(buf) -1] = "\0"; write(soc, buf, 1024); read(soc, buf, 1024); fprintf(stdout, "%s\n", buf); } close(soc); return 0; } サーバー側プログラム #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <unistd.h> #include <sys/socket.h> #include <arpa/inet.h> #define SOCK_NAME "./socket" int main() { int i; int fd1, fd2; struct sockaddr_in saddr; struct sockaddr_in caddr; int len; int ret; char buf[1024]; if((fd1 =socket(AF_INET, SOCK_STREAM, 0)) < 0 ){ perror("socket"); exit(1); } memset((char *)&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr=INADDR_ANY; saddr.sin_port=htons(1357); unlink(SOCK_NAME); if(bind(fd1, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { perror("bind"); exit(1); } if(listen(fd1,5) < 0 ) { perror("listen"); exit(1); } while(1){ len = sizeof(caddr); if((fd2 = accept(fd1, (struct sockaddr *)&caddr, &len)) < 0){ perror("accept"); exit(1); } fprintf(stderr, "Connection established: socket %d used.\n", fd2); while((ret = read(fd2, buf, 1024)) > 0 ){ fprintf(stderr, "read: &s\n", buf); for(i=0; i<ret; i++) if(islower(buf[i])) buf[i] = toupper(buf[i]); if(isupper(buf[i])) buf[i] = tolower(buf[i]); fprintf(stderr, "write: %s\n", buf); write(fd2, buf, 1024); } close(fd2); } close(fd1); return 0; }

  • VC++でのメールの添付ファイル受信

    http://www.masukawa.co.jp/sdk/40.html のサイトを参考にしてソースを組んでいます。 ですが BOOL Pop3RecvDataToFile(SOCKET sock, int i, char *filename) { char *get, tmp, buff[BUFF_SIZE]; int size, pos; FILE *fp; if (!SockCmd1(sock, "RETR %d", i, buff, "+OK")) return FALSE; if ((fp = fopen(filename, "wb")) == NULL) return FALSE; tmp = '\0'; pos = 0; for (;;) { size = recv(sock, buff, BUFF_SIZE, 0); for (get=buff; get<(buff+size); get++) { if (*get=='\0' || *get=='\r') continue; if (++pos == 1) { if (*get != '\n') { tmp = *get; continue; } } else if (pos == 2) { if (tmp=='.' && *get=='\n') goto FINISH; if (tmp!='.' || *get!='.') fputc(tmp, fp); } fputc(*get, fp); if (*get == '\n') pos = 0; } } FINISH: fclose(fp); return TRUE; } のfor分で無限ループしています。 その理由がわかりません。どうすればよいでしょうか?

  • ネットで落ちていた「Excelで作ったデータ(CSVファイル)の読み込

    ネットで落ちていた「Excelで作ったデータ(CSVファイル)の読み込みプログラム」をそのままコンパイルして実行しようと思ったのですが、 sample.c: In function 'main': sample2.c:9: warning: return type of 'main' is not 'int' と、表示されてしまいます。 プログラミング初心者なので、どこが間違っているのかわかりません。 回答またはアドバイスの程、よろしくお願いいたします。 ネットで落ちていたプログラムを以下に記載します。 sample2.c #include <stdio.h> #define MAX_ITEM_SIZE 100 #define MAX_LINE_SIZE 1024 char *GetCSVItem(char *wp, char *buff, int size); void main(int argc, char *argv[]) { FILE *fp; char buff[MAX_LINE_SIZE], *wp, item[3][MAX_ITEM_SIZE]; int i1, len; if(argc != 2){ printf("コマンドの入力形式が間違っています.\n"); return; } fp = fopen(argv[1], "r"); if(fp == NULL){ printf("ファイルがオープンできません[%s].\n", argv[1]); return; } for(;;){ if(fgets(buff, MAX_LINE_SIZE, fp) == NULL) break; len = strlen(buff); if(len == 0 || buff[len-1] != '\n'){ if(feof(fp) == 0){ printf("データが不正です[%s].\n", buff); return; } } buff[len-1] = '\0'; wp = buff; if((wp = GetCSVItem(wp, item[0], MAX_ITEM_SIZE)) == NULL){ printf("エラー(1)\n"); break; } if((wp = GetCSVItem(wp, item[1], MAX_ITEM_SIZE)) == NULL){ printf("エラー(2)\n"); break; } if((wp = GetCSVItem(wp, item[2], MAX_ITEM_SIZE)) == NULL){ printf("エラー(3)\n"); break; } if(*wp != '\0'){ printf("エラー(4)\n"); break; } for(i1 = 0; i1 < 3; i1++){ printf("%d:%s\n", i1+1, item[i1]); } } fclose(fp); } char *GetCSVItem(char *wp, char *buff, int size) { int i1; buff[0] = '\0'; while(*wp == ' ' || *wp == '\t') wp++; if(*wp == '\0'){ return(NULL); } for(i1 = 0; i1 < MAX_ITEM_SIZE; i1++, wp++){ if(i1 >= size) return(NULL); buff[i1] = *wp; if(*wp == '\0'){ buff[i1] = '\0'; return(wp); } if(*wp == ','){ wp++; buff[i1] = '\0'; break; } } return(wp); }

専門家に質問してみよう