c로 메일을 보내는 방법에 관한 질문 입니다.^^

dux의 이미지

popen() 이나 system() 등의 함수를 써서 sendmail 등의 프로그램을 통해서 메일을 보낼 수 있지만, 그렇게하면 새로운 프로세스가 띄워지기 때문에 리스템 리소스를 더 먹을 수도 있을 것 같습니다.
지금 목표가 최소한의 시스템 리소스를 잡아먹게 하는 것입니다.
메일을 보내는 라이브러리 함수가 따로 있나요?^^;
제가 찾아본 바로는 없어서요~
만일 메일을 보내는 함수를 따로 작성한다면 얼마나 하드코어적인 작업이 필요한지 알고 싶네요.. 즉 얼마나 low level 까지 건드려야 하는지..
대략 SMTP프로토콜을 마구 주물러야 한다면 낭패겠네요..ㅎㅎ

vinus의 이미지

RFC-821, RFC-822, RFC-2822 가 관련된 문서 입니다.

목적이 메시지 전달이라면,그렇게 어렵지는 않습니다.

>>>행복한 웃음<<<

cdpark의 이미지

popen에 대한 시스템 로드를 걱정하실 정도라면 수십만통의 메일을 보내는 서버를 만드시나요?

그렇다면 sendmail 대신에 qmail을 쓸 걱정부터 하시는게 순서일 듯 싶네요.

vinus의 이미지

q-mail이라..

그렇게 말씀하니까 한가지 방법이 떠오르는 군요.
qmail에서 메일 보낼때 사용하는 데이타 형식대로 메시지를 만든다음,
qmail에서 메일 전송하도록 하면 되지 않을까요.
qmail의 송신 메일 저장장소에(이걸 뭐라 부르는지 모르지만...)파일을 덤프 하기만 하면, 메일은 qmail이 전송 할테니 좀더 쉽지 않을까 하는 생각이 드는 군요.

>>>행복한 웃음<<<

markboy의 이미지

구글에서 smtp library 정도로 검색해보면 쓸만한 라이브러리를 검색하실 수 있습니다. 굳이 모두 작성하실 필요는 없을 것 같네요.

revizes의 이미지

흠..오렐리 책 보면 간단하게 c로 짤수 있을텐데요..
4년전엔가 MUA 만드는데...메세지 전송 테스트하는데..
단순히 소켓 열어서..
EHLO였던가...격이..잘..

흠..암튼...100라인 안쪽으로 짤 수 있을듯...
물론..메세지 전송만 한다면요...

다 덤벼! 다 받아줄께!!

saxboy의 이미지

SMTP 는 별로 하드코어한 프로토콜이 아니라서 RFC읽으면서 몇시간이면 충분히 구현할 수 있을 정도의 수준일텐데요. attachment까지 처리한다고 해도 각종 인코딩 함수는 대부분 구글 사마가 보여주시니 크게 힘들만한 구현작업이 아닙니다.

메일과 한글 인코딩의 역사적 배경에 대해 공부를 한다면 여러가지로 시간이 소요되겠지만... ;-)

niemand의 이미지

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <getopt.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

static char *from_addr  = NULL;                /* 보내는 사람 주소        */
static char *reply_addr = NULL;                /* 받는 사람 주소        */
static char *mailhost   = NULL;                /* 메일서버 주소        */
static int   mailport   = 25;                /* 메일서버 포트        */
static char *subject    = 0;                /* 메일 제목                 */
static FILE *sfp;
static FILE *rfp;

/*
** 메일서버에서 응답받기
*/
void Get_Response(void)
{
    char buf[BUFSIZ];

    while (fgets(buf, sizeof(buf), rfp)) {
        buf[strlen(buf)-1] = 0;
                /*
        printf("%s --> %s\n", mailhost, buf);
                */
        if (!isdigit(buf[0]) || buf[0] > '3') {
            printf("unexpected reply: %s\n", buf);
            exit(-1);
        }
        if (buf[4] != '-')
            break;
    }
    return;
}

/*
** 메일서버로 내용 전송하고 응답받기
*/
void Chat(char *fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    vfprintf(sfp, fmt, ap);
    va_end(ap);
  
        /*
    va_start(ap, fmt);
    printf("%s <-- \n", mailhost);
    vprintf(fmt, ap);
    va_end(ap);
        */

    fflush(sfp);
    Get_Response();
}

/*
**  main 함수
*/

void Usage(void)
{
        printf("\n");
        printf("usage   : cymail [-S host] [-s subject] <-r reply-addr> FILE\n");
        printf("options :\n");
        /*
        printf("  -S, --smtp-host=HOST        host where MTA can be contacted via SMTP\n")
        */
        printf("          -S,       host where MTA can be contacted via SMTP\n");
        printf("          -s,       subject line of message\n");
        printf("          -r,       address of the sender for replies\n");
        printf("\n");
        exit(0);
}

int main(int argc, char **argv)
{
        FILE *fpFile;
    char buf[BUFSIZ];
    char my_name[BUFSIZ];
    struct sockaddr_in sin;
    struct hostent *hp;
    struct servent *sp;
        int c;
    int s;
    int r;
    char *cp;

        opterr = 0;

        while((c = getopt(argc, argv, "S:s:r:")) != -1)
        {
                switch(c)
                {
                        case 'S':
                                mailhost = optarg;
                                break;
                        case 's':
                                subject = optarg;
                                break;
                        case 'r':
                                from_addr = optarg;
                                reply_addr = optarg;
                                break;
                        case '?':
                                Usage();
                                exit(-1);
                }
        }

        if (mailhost == NULL)
        {
                if ((cp = getenv("SMTPSERVER")) != NULL)
                {
                        mailhost = cp;
                }
                else
                {
                        printf("SMTPSERVER is not setting\n");        
                        exit(-1);
                }
        }

        if( optind != (argc -1))
        {
                Usage();
                exit(-1);
        }

        if(from_addr == NULL)
        {
                Usage();
                exit(-1);
        }

    /*
     *  메일 서버에 연결
     */

    if ((hp = gethostbyname(mailhost)) == NULL) {
        printf("%s: unknown host\n", mailhost);
        exit(-1);
    }
    if (hp->h_addrtype != AF_INET) {
        printf("unknown address family: %d\n", hp->h_addrtype);
        exit(-1);
    }

    memset((char *)&sin, 0, sizeof(sin));
    memcpy((char *)&sin.sin_addr, hp->h_addr, hp->h_length);

    sin.sin_family = hp->h_addrtype;
    sin.sin_port = htons(mailport);

    if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        printf("socket: error\n");
        exit(-1);
    }
    if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
        printf("connect: error\n");
        exit(-1);
    }
    if ((r = dup(s)) < 0) {
        printf("dup: error\n");
        exit(-1);
    }
    if ((sfp = fdopen(s, "w")) == 0) {
        printf("fdopen: error\n");
        exit(-1);
    }
    if ((rfp = fdopen(r, "r")) == 0) {
        printf("fdopen: error\n");
        exit(-1);
    }

    /* 
     *  SMTP 헤더보내기
     */
    Get_Response(); /* 초기 메시지 받기 */
        /*
    Chat("HELO %s\r\n", my_name);
        */
    Chat("mail FROM: <%s>\r\n", from_addr);
    Chat("RCPT TO: <%s>\r\n", reply_addr);
    Chat("DATA\r\n");

    /* 
     *  메일 제목
     */
        if( subject != NULL)
        {
            fprintf(sfp, "Subject: %s\r\n", subject);
            fprintf(sfp, "\r\n");
    }

    /* 
     *  메일 내용 읽기
     */
        if ((fpFile = fopen(argv[argc - 1], "r")) == NULL )
        {
                printf("no message file \n");
                exit(-1);
        }
        else
        {
                while(fgets(buf, sizeof(buf), fpFile))
                {
                        buf[strlen(buf)-1] = 0;
                        if (strcmp(buf, ".") == 0)
                        {
                                fprintf(sfp, ".\r\n");
                        }
                        else
                        {
                                fprintf(sfp, "%s\r\n", buf);
                        }
                }
                fclose(fpFile);
        }

    /* 
     *  내용 종료 및 통신 종료
     */
    Chat(".\r\n");
    Chat("QUIT\r\n");

        printf("Your mail is sended successfully !!\n");
    exit(0);
}

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.