Avatar billede c-skau Nybegynder
10. december 2006 - 12:08 Der er 11 kommentarer og
1 løsning

"Stream" e-mail

Hej,

Ved brug af eksemplet på http://www.eksperten.dk/spm/648186 har jeg fået bakset noget kode sammen der umiddelbart ser ud til at virke.
Det er jo meget rart - hvis det ikke lige havde været fordi koden fejler når først min datamængde overskrider en hvis grænse.
Jeg er klar over at TCP-pakker har en grænse på størrelsen ( Mener det er ~1024 bytes.. ), men det omgår jeg som sagt ved at "streame" data i stedet for at sende det i én enkelt pakke.
Helt simpelt forklaret så hugger jeg min data i små stykker og smider dem i hver sin 'send()'.
Det egentlige problem er nu at selv denne metode synes at fejle. Mit spørgsmål lyder derfor; Er min metode ubrugbar eller er der noget jeg komplet har overset?

Takker på forhånd
C-Skau
Avatar billede arne_v Ekspert
10. december 2006 - 15:40 #1
der burde ikke være noget galt med at sende lange emails

får du sendt en \r\n en gang imellem i teksten ?
Avatar billede c-skau Nybegynder
10. december 2006 - 21:27 #2
Skulle jeg bestemt mene jeg gør.
Jeg bruger følgende kode;

        cout << ">> " << strbuf.c_str();
        status = send( sd, strbuf.c_str(), strlen( strbuf.c_str() ), 0 );

Jeg looper vel at mærke denne kode, og får endda fine outputs i consolen.
Noget ala;

>> HELO phi
>> MAIL FROM: <mail@mail.mail>
...

Jeg har tjekket mit output gennem mange gange og finder intet besynderligt.
Avatar billede c-skau Nybegynder
12. december 2006 - 13:20 #3
Ville det hjælpe noget hvis jeg postede hele koden (Evt. med eks. på output) på pastebin?
Avatar billede arne_v Ekspert
12. december 2006 - 16:40 #4
det tror jeg, fordi umiddelbart kan jeg ikke se noget problem
Avatar billede c-skau Nybegynder
13. december 2006 - 13:19 #5
Takker.
Desværre ser det ud til at PasteBin har lidt problemer for tiden.
Har du tilfældigvis et alternativ forslag i baghånden?
Avatar billede arne_v Ekspert
14. december 2006 - 04:06 #6
kan du ikke bare poste koden her ?
Avatar billede c-skau Nybegynder
14. december 2006 - 09:00 #7
Det er da en mulighed, men med +500 linjer vil jeg nøjes med udklip:

string buildmail( ttmail * ttm, char * ownhost )
{
    string mail;

    char *to = (char *)ttm->to.c_str();
    char *cc = (char *)ttm->cc.c_str();
    char *bcc = (char *)ttm->bcc.c_str();
    char *from = (char *)ttm->from.c_str();
    char *subj = (char *)ttm->subj.c_str();
    char *body = (char *)ttm->body.c_str();
    char *atchname = (char *)ttm->atchname.c_str();
    char* atchdata = ttm->atchdata;

    char *buf = (char *)malloc( 2000 + strlen(body) + strlen(atchdata) );

    // Do if chars contain data
    bool do_cc = strlen(cc);
    bool do_bcc = strlen(bcc);
    bool do_atch = strlen(atchname);

    //! --------------------------------------------------- Header --
    // Standart header
    sprintf( buf,
            "HELO %s\r\n"
            "MAIL FROM: <%s>\r\n"
            "RCPT TO: <%s>\r\n"
            "DATA\r\n",
            ownhost,from,to
            );
    mail += buf;

    //! --------------------------------------------------- DATA.head
    // Data header
    sprintf( buf,
            "Return-Path: <%s>\r\n"
            "From: %s\r\n"
            "To: %s\r\n",
            from,from,to
            );
    mail += buf;

    if( do_cc )
    {
        sprintf( buf, "Cc: %s\r\n", cc );
        mail += buf;
    }

    if( do_bcc )
    {
        sprintf( buf, "Bcc: %s\r\n", cc );
        mail += buf;
    }

    sprintf( buf,
            "Subject: %s\r\n"
            "Mime-version: 1.0\r\n",
            subj
            );
    mail += buf;

    //! --------------------------------------------------- DATA.body

    if( do_atch )
    {
        // Multi-format HEADER
        sprintf( buf,
                "Content-Type: multipart/mixed; boundary=------------010206060501050706020108\r\n"
                "\r\n"
                "--------------010206060501050706020108\r\n"
                );
        mail += buf;
    }

    // Body
    sprintf( buf,
            "Content-Type: text/plain; charset=ISO-8859-1; format=flowed\r\n"
            "Content-Transfer-Encoding: 7bit\r\n"
            "\r\n"
            "%s\r\n" // cont
            "\r\n",
            body
            );
    mail += buf;

    if( do_atch )
    {
        // ATTACH FILE
        sprintf( buf,
                "--------------010206060501050706020108\r\n"
                "Content-Type: application/octet-stream; name=%s\r\n"
                "Content-Transfer-Encoding: base64\r\n"
                "Content-Disposition: attachment; filename=\"%s\"\r\n"
                "\r\n",
                atchname, atchname
                );
        mail += buf;

        mail += atchdata;

        sprintf( buf,
                "\r\n" // break from atchdata
                "--------------010206060501050706020108--\r\n"
                );
        mail += buf;
    }

    //! --------------------------------------------------- Footer
    // Footer
    sprintf( buf,
            "\r\n.\r\n"
            "QUIT\r\n"
            );
    mail += buf;

    free(buf);

    return mail;
}

//! --------------------------------------------------------------------------------

void mailsend( ttmail * ttm )
{
    int sd,status,tmp;
    char ownhost[100];
    struct sockaddr local, remote;
    struct hostent *hostinfo;

    string retmail;

    char *hostname = (char *)ttm->host.c_str();

    string::size_type loc;
    int oldloc = 0;
    string strbuf("");

    /* create socket */
    sd = socket( AF_INET, SOCK_STREAM, 0 ); //socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

    if( sd < 0 )
    {
        printf( "Error creating socket: %s\n", strerror(errno) );
        goto fin;
    }

    /* bind socket */
    local.sa_family = AF_INET;
    memset( local.sa_data, 0, sizeof(local.sa_data) );
    status = bind( sd, &local, sizeof(local) );

    if ( status < 0 )
    {
        printf( "Error binding socket: %s\n", strerror(errno) );
        goto fin;
    }

    /* lookup host */
    hostinfo = gethostbyname( hostname );
    if ( !hostinfo )
    {
        printf( "Error looking up host: %s\n", hostname );
        goto fin;
    }

    /* connect to host */
    remote.sa_family = hostinfo->h_addrtype;
    memcpy( remote.sa_data+2, hostinfo->h_addr_list[0], hostinfo->h_length );
    *((short *)remote.sa_data) = 25;
    tmp = remote.sa_data[0];
    remote.sa_data[0] = remote.sa_data[1];
    remote.sa_data[1] = tmp;

    status = connect( sd, &remote, sizeof(remote) );

    if (status!=0)
    {
        printf( "Error connecting to host: %s port: %d\n", hostname, 25 );
        goto fin;
    }

    /* send email */
    gethostname( ownhost, sizeof(ownhost) );

    retmail = buildmail( ttm, ownhost );

//! Print complete mail data to console
//    cout << retmail.c_str() << endl;

//! Stream complete mail data to file ( mail.tmp )
    FILE* filout = fopen( "mail.tmp", "wb+" );
    fwrite( retmail.c_str(), 1, strlen(retmail.c_str()), filout );
    fclose( filout );

//! Send complete mail data to STMP server
//    status = send( sd, retmail.c_str(), strlen( retmail.c_str() ), 0 );

//! STREAM complete mail data to STMP server
    cout << "Sending mail data: " << endl << endl;

    loc = retmail.find( '\r\n', 0 );
    loc++;

    do{
        strbuf = retmail.substr( oldloc, (loc - oldloc) );
        oldloc = loc;

        cout << ">> " << strbuf.c_str();
        status = send( sd, strbuf.c_str(), strlen( strbuf.c_str() ), 0 );

        if( loc >= retmail.length() )
            break;

        loc = retmail.find( '\r\n', loc );
        loc++;
    }while( loc != string::npos );

//! Report transmission status
    if( status < 0 )
    {
        printf( "Error sending GET request\n" );
        goto fin;
    }
    else
    {
        cout << "Final status: " << status << endl;
    }

fin:
    closesocket(sd);
    return;
}

//! --------------------------------------------------------------------------------

int main( int argc, char *argv[] )
{
    ttmail ttm;

    config( "cfg.ini", &ttm );

    if(argc > 1)
        handlearg( argc, argv, &ttm );

    if( ttm.atchname != "" )
    {
        FILE* filin = fopen( ttm.atchname.c_str(), "rb" );
        FILE* filout = fopen( "atch.tmp", "wb" );
        int len = base64_encode( filin, filout );
        fclose( filin );
        fclose( filout );

        ttm.atchdata = (char *)malloc( len );
        filout = fopen( "atch.tmp", "r" );
        fread( ttm.atchdata, 1, len, filout );
        fclose( filout );
    }

    WSADATA WSAData;
    WSAStartup( 0x0101, &WSAData );

    mailsend( &ttm );

    WSACleanup();

    return 0;
}
Avatar billede arne_v Ekspert
15. december 2006 - 04:46 #8
får du ikke en warning på '\r\n' ?
Avatar billede arne_v Ekspert
15. december 2006 - 04:48 #9
og hvorfor hælder du ikke bare hele retmail ud ?

du behøver ikke sende en linie ad gangen !
Avatar billede c-skau Nybegynder
15. december 2006 - 16:17 #10
*host* jo, '\r\n' giver mig en "multi-character character constant". Desværre kan warnings ignoreres, hvilket jeg alt for ofte har det med at gøre .. i det mindste til jeg har fået resten af koden til at virke.
Du mener vel ikke at det kan være der problemet ligger ?

Jeg har tilgengæld valgt bevidst at dumpe indholdet af 'retmail' én linie ad gangen af "analytiske årsager" - Altså for at sikre mit at linieopdelinger kommer de præcis samme steder jeg forventer. ( Jeg har med tiden lært at man absolut ikke skal tage den slags for givet ;)
Avatar billede arne_v Ekspert
16. december 2006 - 04:24 #11
nej, men jeg bed bare mærke i det

der er ikke umiddelbart noget som springer i øjnene

men en ting du skal checke er at alle linier er afsluttet med \r\n
Avatar billede c-skau Nybegynder
01. august 2007 - 19:08 #12
Hvis på tiden den her bliver lukket !
Kan knap huske hvordan jeg fiksede det her, sorry

PS, Arne hvis du vil have pointene så må du endelig sige til, så skal du nok få dem :
Men nu lukke tråden her.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester