Avatar billede inglenook Praktikant
23. februar 2004 - 18:56 Der er 11 kommentarer og
1 løsning

C++ kode til at sende emails i HTML format fra Linux (Red Hat 9)

Jeg mangler noget kode der vil lade mig sende email fra mit program i HTML format. Har ikke fundet noget der kunne bruges.

Jeg kan goere det fra Windows (VB6) ved at bruge min internet udbyders SMTP server, men det er jo lidt andet med C++ og Linux......

Nogen bud...?
Avatar billede arne_v Ekspert
23. februar 2004 - 20:43 #1
Du laver en socket connection til port 25 på mail serveren og
skriver emailen jævnfør RFC 821, 822 og MIME standarden.

Simpelt eksempel:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include <sys/socket.h>
#include <fcntl.h>
#include <netdb.h>
#include <errno.h>

void mailsend(char *hostname,char *to,char * from,char *subj,char *body)
{
  int sd,status,tmp;
  char *buf,ownhost[100];
  struct sockaddr local,remote;
  struct hostent *hostinfo;
  /* create socket */
  sd=socket(AF_INET,SOCK_STREAM,0);
  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));
  buf = malloc(2000+strlen(body));
  sprintf(buf,"HELO %s\r\n"
              "MAIL FROM: <%s>\r\n"
              "RCPT TO: <%s>\r\n"
              "DATA\r\n"
              "Return-Path: <%s>\r\n"
              "From: %s\r\n"
              "To: %s\r\n"
              "Subject: %s\r\n"
              "MIME-version: 1.0\r\n"
              "Content-type: text/html; Charset=iso-8859-1\r\n"
              "\r\n"
              "%s\r\n"
              ".\r\n"
              "QUIT\r\n",ownhost,from,to,from,from,to,subj,body);
  status=send(sd,buf,strlen(buf),0);
  if(status<0) {
      printf("Error sending GET request\n");
      goto fin;
  }
  free(buf);
fin:
  close(sd);
  return;
}

int main(int argc,char *argv[])
{
  mailsend("minmailserver", "dig@ditdomain.dk", "mig@mitdomain.dk", "Dette er en test", "<a href='http://www.eksperten.dk/'>E</a>");
  return 0;
}
Avatar billede inglenook Praktikant
23. februar 2004 - 23:00 #2
Alletiders, jeg proever det i morgen aften.

Tak for det !
Avatar billede inglenook Praktikant
24. februar 2004 - 19:59 #3
htmlmail.cpp: In function `void mailsend(char*, char*, char*, char*, char*)':
htmlmail.cpp:55: `gethostname' undeclared (first use this function)
htmlmail.cpp:55: (Each undeclared identifier is reported only once for each
  function it appears in.)
htmlmail.cpp:56: invalid conversion from `void*' to `char*'
htmlmail.cpp:78: `close' undeclared (first use this function)
Avatar billede inglenook Praktikant
24. februar 2004 - 21:48 #4
arne_v, jeg er ikke saa skrap til cpp, har du en ide om hvad jeg skal kigge efter..?
Avatar billede arne_v Ekspert
24. februar 2004 - 22:51 #5
Mystisk jeg har testet på Redhat 7.2 - no problems

den midterste kan fjernes med:

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

den første og den sidste er et spørgsmål includes - prøv

man gethostname
man close

for at finde de rette .h filer
Avatar billede inglenook Praktikant
26. februar 2004 - 01:52 #6
ok, skulle include unistd.h saa compilede det fint. Har rodet lidt rundt med det og fundet ud af jeg kan ikke faa det til at virke naar jeg sender alt paa een gang. Er noedt til at sende det linje for linje til serveren og vente paa de rette svar derfra (220, 250 etc.) Har du en go' ide til at vente paa svar (og checke koden, altsaa de tre karakterer laengst til venstre), evt. som en function ? Jeg proevede dette for at se hvilket svar jeg fik, men hvis der endnu ikke er noget svar vil programmet haenge.....
ix=0;
  while ((len=recv(sd,resp+ix,sizeof(resp)-ix-1,0))>0) {
      ix = ix + len;
  }
  resp[ix]='\0';
  printf("%s\n",resp);

I VB6 bruger jeg denne procedure:

Public Sub WaitFor(ResponseCode As String)
    Start = Timer ' Time event so won't get stuck in loop
    While Len(Response) = 0
        Tmr = Start - Timer
        DoEvents ' Let System keep checking for incoming response **IMPORTANT**
        If Abs(Tmr) > 50 Then ' Time in seconds to wait
            SMTPfailure = True ' MsgBox "SMTP service error, timed out while waiting for response", 64, MsgTitle
            Exit Sub
        End If
    Wend
    While Left(Response, 3) <> ResponseCode
        DoEvents
        If Abs(Tmr) > 50 Then
            SMTPfailure = True
            x = MsgBox("SMTP service error, impromper response code. Code should have been: " + ResponseCode + " Code recieved: " + Response, 64, "Error")
            Exit Sub
        End If
    Wend
Response = "" ' Set response code to blank **IMPORTANT**
End Sub

Kan noget lignende laves i C++ ?

Der er selvfoelgeligt flere point paa hoejkant ;-)
Avatar billede inglenook Praktikant
26. februar 2004 - 01:55 #7
Ovenstaaende virker selvfolgeligt sammen med dette:

Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
    Winsock1.GetData Response ' Check for incoming response
    lblResponse.Caption = Left(Response, 3)
End Sub
Avatar billede arne_v Ekspert
26. februar 2004 - 09:02 #8
Du kan lave en såkaldt non blocking read !
Avatar billede arne_v Ekspert
26. februar 2004 - 09:32 #9
Følgende eksempel er ganske vist til HTTP ikke SMTP men viser
non blocking read:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#include <sys/socket.h>
#include <fcntl.h>
#include <netdb.h>
#include <errno.h>

void get(char *hostname,int port,char *path,int noblock)
{
  int sd,status,len,ix,tmp;
  char cmd[512],resp[51200];
  struct sockaddr local,remote;
  struct hostent *hostinfo;
  time_t t;
  /* create socket */
  sd=socket(AF_INET,SOCK_STREAM,0);
  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)=port;
  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,port);
      goto fin;
  }
  /* send GET request */
  sprintf(cmd,"GET %s HTTP/1.1\r\nHost: %s\r\n\r\n",path,hostname);
  status=send(sd,cmd,strlen(cmd),0);
  if(status<0) {
      printf("Error sending POST request\n");
      goto fin;
  }
  /* read response */
  ix=0;
  if(noblock) {
      status=fcntl(sd,F_SETFL,O_NONBLOCK);
      if(status<0) {
        printf("Error setting socket nonblocked: %s\n",strerror(errno));
        goto fin;
      }
      t=time(NULL);
      while (time(NULL)<(t+5)) {
        len=recv(sd,resp+ix,sizeof(resp)-ix-1,0);
        ix = ix + len;
        printf("no blocking read %d bytes\n",len);
        sleep(1);
      }
  } else {
      while ((len=recv(sd,resp+ix,sizeof(resp)-ix-1,0))>0) {
        ix = ix + len;
        printf("blocking read %d bytes\n",len);
      }
  }
  resp[ix]='\0';
  /*printf("%s",resp);*/
fin:
  close(sd);
  return;
}

int main(int argc,char *argv[])
{
  get("www.xxxx.dk",80,"/",0);
  get("www.xxxx.dk",80,"/",1);
}
Avatar billede inglenook Praktikant
01. marts 2004 - 19:57 #10
hmm, kunne ikke faa det til at virke. Har configureret min sendmail til at videresende til min ISP's SMTP server i stedet. Laegger du lige et svar mere saa du kan faa lidt flere point ?
Tak for hjaelpen !!
Avatar billede arne_v Ekspert
01. marts 2004 - 20:01 #11
Når der er accepteret et svar kan man ikke uddele flere point for
spørgsmålet.

Hvis du vil give mig lidt flere point for non blocking, så kan du
oprette et spørgsmål "Point til arne_v" med et link til dette
spørgsmål.
Avatar billede inglenook Praktikant
01. marts 2004 - 20:07 #12
OK, kig efter Point til Valhoej
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