SMTP 서버 + 보안연결 메일 보내기

출처: http://www.codeproject.com/Articles/98355/SMTP-Client-with-SSL-TLS

공개된 CSmtp 라이브러리를 사용하여.. 메일 보내기..

CSmtp_v2_3_ssl.zip

아래는 MinGW를 사용하여 gmail의 TLS 보안 연결로 메일 보내는 예제..
OpenSSL 라이브러리 필요하며, 리눅스에서도 사용 가능..

#include "CSmtp.h"
#include <iostream>

int main()
{
	bool bError = false;

	try
	{
		CSmtp mail;

#define test_gmail_tls

#if defined(test_gmail_tls)
		mail.SetSMTPServer("smtp.gmail.com",587);
		mail.SetSecurityType(USE_TLS);
#elif defined(test_gmail_ssl)
		mail.SetSMTPServer("smtp.gmail.com",465);
		mail.SetSecurityType(USE_SSL);
#elif defined(test_hotmail_TLS)
		mail.SetSMTPServer("smtp.live.com",25);
		mail.SetSecurityType(USE_TLS);
#elif defined(test_aol_tls)
		mail.SetSMTPServer("smtp.aol.com",587);
		mail.SetSecurityType(USE_TLS);
#elif defined(test_yahoo_ssl)
		mail.SetSMTPServer("plus.smtp.mail.yahoo.com",465);
		mail.SetSecurityType(USE_SSL);
#endif

		mail.SetLogin("user_id");
		mail.SetPassword("user_password");
  		mail.SetSenderName("User");
  		mail.SetSenderMail("user@domain.com");
  		mail.SetReplyTo("user@domain.com");
  		mail.SetSubject("The message");
  		mail.AddRecipient("friend@domain2.com");
  		mail.SetXPriority(XPRIORITY_NORMAL);
  		mail.SetXMailer("The Bat! (v3.02) Professional");
  		mail.AddMsgLine("Hello,");
		mail.AddMsgLine("");
		mail.AddMsgLine("...");
		mail.AddMsgLine("How are you today?");
		mail.AddMsgLine("");
		mail.AddMsgLine("Regards");
		mail.ModMsgLine(5,"regards");
		mail.DelMsgLine(2);
		mail.AddMsgLine("User");

  		//mail.AddAttachment("../test1.jpg");
  		//mail.AddAttachment("c:\\test2.exe");
		//mail.AddAttachment("c:\\test3.txt");
		mail.Send();
	}
	catch(ECSmtp e)
	{
		std::cout << "Error: " << e.GetErrorText().c_str() << ".\n";
		bError = true;
	}
	if(!bError)
		std::cout << "Mail was send successfully.\n";
	return 0;
}

libcurl 을 이용하여 웹페이지 긁어오기

MingW용 libcurl을 빌드후에.. http 페이지 긁어오는 걸 테스트해 봄..
static 빌드시에.. curl.h 파일 include 전에 CURL_STATICLIB define 필요.

#include <stdlib.h>
#include <stdio.h>
#define CURL_STATICLIB
#include <curl/curl.h>

struct url_data {
    size_t size;
    char* data;
};

size_t write_data(void *ptr, size_t size, size_t nmemb, struct url_data *data) {
    size_t index = data->size;
    size_t n = (size * nmemb);
    char* tmp;

    data->size += (size * nmemb);

#ifdef DEBUG
    fprintf(stderr, "data at %p size=%ld nmemb=%ld\n", ptr, size, nmemb);
#endif
    tmp = realloc(data->data, data->size + 1); /* +1 for '\0' */

    if(tmp) {
        data->data = tmp;
    } else {
        if(data->data) {
            free(data->data);
        }
        fprintf(stderr, "Failed to allocate memory.\n");
        return 0;
    }

    memcpy((data->data + index), ptr, n);
    data->data[data->size] = '\0';

    return size * nmemb;
}

char *handle_url(char* url) {
    CURL *curl;

    struct url_data data;
    data.size = 0;
    data.data = malloc(4096); /* reasonable size initial buffer */
    if(NULL == data.data) {
        fprintf(stderr, "Failed to allocate memory.\n");
        return NULL;
    }

    data.data[0] = '\0';

    CURLcode res;

    curl = curl_easy_init();
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, url);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
        res = curl_easy_perform(curl);
        if(res != CURLE_OK) {
                fprintf(stderr, "curl_easy_perform() failed: %s\n",  
                        curl_easy_strerror(res));
        }

        curl_easy_cleanup(curl);

    }
    return data.data;
}

int main(int argc, char* argv[]) {
    char* data;
    data = handle_url("http://www.findip.kr");

    if(data) {
        printf("%s\n", data);
        free(data);
    }

    return 0;
}
$ gcc http.c -o http.exe -I/workspace/ETC/tclpackages/3rdparty/lib/curl-7.42.1/release/win32/include -L/workspace/ETC/tclpackages/3rdparty/lib/libssh2-1.4.4-20140926/release/win32/lib -L/workspace/ETC/tclpackages/3rdparty/lib/curl-7.42.1/release/win32/lib -L/workspace/ETC/tclpackages/3rdparty/lib/openssl-1.0.2a/release/win32/lib -lcurl -lws2_32 -lcrypt32 -lssh2 -lssl -lcrypto -lws2_32 -lgdi32	-lcrypt32 -lwldap32 /workspace/ETC/tclpackages/3rdparty/lib/zlib-1.2.8/release/win32/lib/libz.a

libconfig

홈페이지1: http://www.hyperrealm.com/libconfig/
홈페이지2: https://github.com/evoskuil/libconfig

libconfig – C/C++ Configuration File Library

INI 포맷보다 진보된 계층 구조의 형태의 포맷을 가지는 Configuration 파일 Reader/Writer 라이브러리

Libconfig is a simple library for processing structured configuration files, like this one: test.cfg. This file format is more compact and more readable than XML. And unlike XML, it is type-aware, so it is not necessary to do string parsing in application code.

Libconfig is very compact — a fraction of the size of the expat XML parser library. This makes it well-suited for memory-constrained systems like handheld devices.

The library includes bindings for both the C and C++ languages. It works on POSIX-compliant UNIX systems (GNU/Linux, Mac OS X, Solaris, FreeBSD) and Windows (2000, XP and later).

#----------------------------
# Example Configuration File
#---------------------------
#

application:
{

 /* This section defines some settings for our
  * main application window, such as size and
  * position.
  */

  window:
  {
    title = "My Application";
    size = { /* width */ w = 640; /* height */ h = 480; };
    pos = { x = 350; y = 250; };
  };

  a = 5;
  b = 6;
  ff = 1E6;
  test-comment = "/* hello\n \"there\"*/";

  test-long-string = "A very long string that spans multiple lines. "
  /* but wait, there's more... */ "Adjacent strings are automatically"
  " concatenated.";

  test-escaped-string = "\"This is\n a test.\"";

  group1:
  {
    x = 5;  y = 10;
    my_array = [ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 ];
    flag = TRUE;

    group2: { zzz = "this is a test"; };

    states = [	"CT", // Connecticut
		"CA", // California
		"TX", // Texas
		"NV", // Nevada
		"FL"  // Florida
    ];
  };

  /* this would cause an error */
  // a = "hi!";
};

binary = [ 0xAA, 0xBB, 0xCC ];

list = ( ( "abc", 123, true ), 1.234, ( /* an empty list */ ) ,[ 1, 2, 3 ],
	   { a = (1, 2, true); } );

books = ( "inventory",
          { title  = "Treasure Island";
            author = "Robert Louis Stevenson";
            price  = 29.99;
            qty    = 5; },
          { title  = "Snow Crash";
            author = "Neal Stephenson";
            price  = 9.99;
            qty    = 8; },
          { } );

# miscellaneous stuff

misc:
{
  port = 5000;
  pi = 3.14159265;
  enabled = FALSE;
  mask = 0xAABBCCDD;
  unicode = "STARGΛ̊TE SG-1"; // UTF-8 string
  bigint = 9223372036854775807L;
  bighex = 0x1122334455667788L;
};


### eof

다운로드: libconfig-1.4.9.tar.gz
Static 빌드 수정된 버전 다운로드: libconfig-1.4.9.zip

Msys2

난 자칭 MinGW 골수팬이다. ㅎ
MinGW와 함께 최고의 조합으로 여겨지는 msys가 msys2 로 업그레이드 되었다.
이제 더욱 쾌적하게 개발을 할수 있게 되었다.
msys2는 cygwin의 기능들이 대부분 이식이 되었고..
Arch 리눅스의 패키지관리 시스템(pacman)이 (우분투의 apt-get과 같은..) 이식 되었다.

msys2 설치

msys2 다운로드 받기: http://sourceforge.net/projects/msys2/files/Base/

현재 20140910 버전이 최신이다. 셋업 파일을 받아도 되나.. 난 tar.xz 파일을 받은후
c:\msys64 에 압축을 풀었다.
아무래도 셋업 파일보단 포터블 버전을 선호한다.
압축 해제후에 msys2_shell.bat 를 실행하면 msys2 환경이 초기 설정이 되고..

1

완료된후 다시 msys2_shell.bat 를 실행시켜주면 깔끔한 msys2 화면을 볼수 있다.

터미널 에뮬레이터 셋팅

msys2는 기본적으로 putty를 포팅한 msys에 최적화된 mintty를 터미널 에뮬레이터로 사용하고 있다.
다음 적절히 mintty를 셋팅 한다. 사용해보니 msys2의 mintty는 한글도 지원이 충실하다.

난 폰트를 나눔고딕코딩이나 Fixedsys 폰트를 좋아하는데
나눔고딕코딩 폰트는 아래에서 다운로드한 후 mintty 에서 셋팅한다.

나눔고딕코딩: http://dev.naver.com/projects/nanumfont/

2

커서 모양도 셋팅하고.. 투명 스타일도 지정하고.. Locale (C), Character set (eucKR) 도 지정한다.
아래는 셋팅후 화면이다. 아주 그럴싸하다.. 리눅스 환경이 부럽지 않다. ㅎㅎ

3

이제 터미널 셋팅이 그럭저럭 된것 같다.

패키지 데이타 베이스 동기화 및 msys2 업그레이드

msys2는 Arch 리눅스의 pacman을 도입하였다.

우선 패키지 데이타 베이스를 동기화 및 msys2를 업그레이드를 한다.

% pacman -Syu

6

만약 msys2 업그레이드시에.. 아래의 에러를 본다면.. 이럴땐 다시 msys2를 실행해주면 된다.
7

다음 지원되는 패키지 목록을 본다.

% pacman -Sl

5

다음 개발시 필요한 패키지를 설치한다. 이정도면 되지 않을까..

% pacman -S wget vim swig mc pkg-config subversion python2 git curl tar binutils autoconf make libtool automake mingw-w64-i686-gcc mingw-w64-x86_64-gcc

의존성도 검사해서 자동 설치해준다.. 이 얼마나 감격스러운가..
8

참고로 gcc는 각 arch 별로 아래에 설치가 된다.
mingw32: mingw-w64-i686-gcc
mingw64: mingw-w64-x86_64-gcc

9

참고로 mingw32_shell.bat를 실행하면 mingw32 폴더의 mingw-w64-i686-gcc를 사용하며,
12
mingw64_shell.bat를 실행하면 mingw64 폴더의 mingw-w64-x86_64-gcc를 사용한다.
13

또한 mingw32_shell.bat와 mingw64_shell.bat를 동시에 실행할수도 있다.
(기존 msys 에서는 동시에 사용이 안됐었다..)

필요 없는 패키지 삭제는 다음과 같이한다.

% pacman -R <package_name>

기타 편의 셋팅

1. .bashrc 셋팅

% vim ~/.bashrc

case "$MSYSTEM" in
        MINGW32)
                export TERMINFO=/mingw32/share/terminfo
                ;;
        MINGW64)
                export TERMINFO=/mingw64/share/terminfo
                ;;
esac

alias ls='ls -hF --color=tty'
alias dir='ls --color=auto --format=vertical'
alias ll='ls -l'
alias la='ls -A'
alias l='ls -CF'
export PS1="\[\e]0;$(gcc -dumpmachine) $(gcc -dumpversion) : \w\a\]\n\[$(tput bold)\]\[$(tput setaf 1)\][\[$(tput setaf 3)\]\u\[$(tput setaf 2)\]@\[$(tput setaf 4)\]\h \[$(tput setaf 5)\]\W\[$(tput setaf 1)\]]\[$(tput setaf 7)\]\\$ \[$(tput sgr0)\]"

아래와 같이 취향대로 셋팅.
15

2. fstab 설정

% vim /etc/fstab

아래와 같이 자주 사용되는 윈도우즈 폴더를 링크한다.
11
저장후 msys2를 다시 실행하면 C:\Works 폴더를 /works 폴더로 접근할 수 있다.

또한 fstab 기능과 상관 없는 기능인데..
기본적으로 msys2 (msys도 마찬가지..) 에서는 윈도우즈 드라이브를 아래와 같이 접근가능하다.

# C:\Windows
$ ls /c/Windows

# D:\Works
$ ls /d/Works

3. .vimrc 설정

vim 기본 설정은 아무것도 안되어 있으므로..
syntax highlight 켜주고.. 백업 파일 안생기게 해주고..

$ vim ~/.vimrc

syntax on
set nobackup

CGAL Build on MinGW

MinGW상에서 CGAL 빌드 방법.

1) download boost sources and compile it (I use boost 1.47.0):

a) generate b2.exe (jam) by typing in a console "bootstrap.bat mingw" 
  b) type in a console: b2.exe --prefix=<absolute_path_to_boost64> 
toolset=gcc address-model=64 variant=debug,release link=static,shared 
threading=multi install 
Before, I tried an external version of boost-jam like described here: 
http://sourceforge.net/apps/trac/mingw-w64/wiki/Building%20Boost
but bjam.exe failed to build boost.

2) build CGAL libraries (I use cgal 3.9):

  a) Use cmake-gui 
  b) before configuring, setup the BOOST_ROOT path variable to you BOOST 
directory. 
  c) optional (this doesn't work for me): setup the Boost_LIBRARYDIR to 
your boost\lib dir 
  d) configure 
  e) optional: check demos and examples and configure again 
  f) generate 
  g) type in a console mingw32-make 
  h) if you have troubles with emmintrin.h and intrin.h, you must add a 
"#include <windows.h>" at the top of the file "all_files.cpp" in the 
src/ImageIO directory generated by cmake 

혹시.. double.h 파일에서 에러가 나면 다음을 추가.

#if defined ( _MSC_VER )
#define CGAL_ALIGN_16  __declspec(align(16))
#elif defined( __GNU__ ) || defined( __MINGW32__ )
#define  CGAL_ALIGN_16 __attribute__((aligned(16))) 
#endif


#ifdef CGAL_USE_SSE2_FABS   
inline double sse2fabs(double a)
{
  static CGAL_ALIGN_16 const union{

3) build demos and examples (if checked in cmake):

 - type mingw32-make demos 
for me, it doesn't link with boost (even with the 2)c) option), so demos 
generation failed. I didn't try examples, but I manualy compile an 
example: circulator 
I used those commands: 
g++ -c circulator_prog1.cpp -frounding-math -I../../include 
-I../../build/include 
-I../../../../boost_1_47_0/mingw64/include/boost-1_47 -o circulator_prog1.o 
g++ circulator_prog1.o -L../../build/lib -lCGAL 
-L../../../../boost_1_47_0/mingw64/lib -lboost_thread-mgw44-mt-1_47 -o 
circulator_prog1.exe 
where /build is the build folder "where to build binaries" for cmake. 

C에서 iconv를 이용한 인코딩 변환

아래는 Euc-Kr을 Utf-8로 변환하는 예제.

#ifndef _UTF8TOEUCKR
#define _UTF8TOEUCKR

#include 
static int UTF8toEUCKR( char *outBuf, int outLength, char *inBuf, int inLength )
{
iconv_t cd = iconv_open( "EUC-KR", "UTF-8" );

int ires = (int)iconv( cd, &inBuf, (size_t*)&inLength, &outBuf, (size_t*)&outLength );

iconv_close(cd);

return ires;
}

#endif

Mini-XML

홈페이지: http://www.msweet.org/projects.php?Z3

다른 라이브러리에 의존적이지 않은 읽기/쓰기가 가능한 작은 XML 파서 라이브러리.
일단 API도 왠만한건 다 지원하는것 같음. MinGW에서 테스트 해보니 굿.

Mini-XML is a small XML library that you can use to read and write XML and XML-like data files in your application without requiring large non-standard libraries. Mini-XML only requires an ANSI C compatible compiler (GCC works, as do most vendors’ ANSI C compilers) and a ‘make’ program.

Mini-XML supports reading of UTF-8 and UTF-16 and writing of UTF-8 encoded XML files and strings. Data is stored in a linked-list tree structure, preserving the XML data hierarchy, and arbitrary element names, attributes, and attribute values are supported with no preset limits, just available memory.

다운로드: mxml-2.8.tar.gz