최초 작성일 : 2011/09/30 09:03 


네이버 카페에서 작성한 글을 그대로 카피앤 페이스트 했더니 소스코드가 본문 영역을
넘어가서 잘려 보이네요. 복사해서 메모장 같은데 붙여넣기 해서 보시면 소스가
다 보입니다...^^;;;

읔...라이브러리 압축한 크기가 93M나 되서 첨부가 안되네요. 링크로 대신합니다.
모두 맥에서 기본 압축한 압축파일입니다.

트위터 : mazdah70


========================================
아이폰에서 사용할 이메일 라이브러리가 생각보다 많지 않네요.
아마도 메일 컴포저를 거치지 않고 바로 메일을 전송하는 기능을 애플이 제한하고 있고
또 기본 메일 앱이 잘 되어있어서 굳이 메일 처리를 앱 내에서 할 필요가 없어서 그런 것 같습니다.

어쨌든 지금 마무리하고 있는 프로젝트에서 메일 라이브러리가 필요해서 겨우겨우 MailCore를 구해서
기본적인 동작 (발송/첨부/pop3수신)은 구현을 했는데요...
문제가 메일 전송시 어떤 한글 문장은 정상적으로 잘 나가는데 어떤 한글 문장은 인코딩 과정에서 null이 리턴되서
제목과 본문, 첨부까지 모두 빈 문자열로 저송이 되어버리네요...ㅠ.ㅠ

이 소스 보시고 확인 좀 부탁드립니다.

일단 문제가 되는 부분은 MailCore 소스 중 MIME 그룹내의 CTMIME.m 파일의 103라인에 있는
render라는 메서드 부분인데요. 짧은 메서드라 소스를 첨부하면 아래와 같습니다.

※음...테이블이 좀 이상하게 그려졌네요...-.-
 
- (NSString *)render {

MMAPString * str = mmap_string_new("");

int col = 0;

int err = 0;

  NSString *resultStr;

    printf("\n1: start str->str = %s\n#######################################################\n", str->str);

    NSLog(@"start str->str = %s\n#######################################################\n", str->str);

    

mailmime_write_mem(str, &col, [self buildMIMEStruct]);

//    NSLog(@"before str->len = %lu", str->len);

    printf("\n1: before str->str = %s\n#######################################################\n", str->str);

    NSLog(@"before str->str = %s\n#######################################################\n", str->str);

err = mmap_string_ref(str);

assert(err == 0);

    

    printf("\n1: after str->str = %s\n#######################################################\n", str->str);

    NSLog(@"after str->str = %s\n#######################################################\n", str->str);

////////////////////////////////////////////////////////////////////////////////////////

//    이전까지는 로그에 내용이 잘 찍히는데 아래 문자열 변환 이후 resultStr이 null이 나옵니다...ㅠ. ㅠ

////////////////////////////////////////////////////////////////////////////////////////

    resultStr = [[NSString allocinitWithCString:str->str encoding:NSUTF8StringEncoding];


    

    mmap_string_free(str);

    NSLog(@"2. CTMIME :: render : resultStr = %@\n#######################################################\n", resultStr);

return [resultStr autorelease];

}






제발 이 부분 좀 해결해주세요...ㅠ.ㅠ


참고로 MailCore는 프레임워크로 만들어 쓰려다 빌드단계에서 실패해서 포기하고 정적 라이브러리로 만들어

사용하고 있습니다. MailCoer.a와 libetpan.a 2개를 같이 사용해야 합니다.


실제 개발시에는 MailCore쪽 메서드만 호출해서 쓰시면 되구요.

기본적으로 MailCore가 IMAP을 위한 코드만을 제공해서 POP3용으로 제가 메서드 하나 추가해놨습니다.


아래는 기본적으로 메일 보내고 받는 메서드 구현부입니다.


※ 메일 보내 기

 

- (void) sendEmailWithData:(NSString *)dataStr {

    CTCoreMessage *coreMessage = [[CTCoreMessage allocinit];   

    

    NSArray *dataStrArr = [dataStr componentsSeparatedByString:@"|"];

    

    const char *sName = "Tester";

    const char *rName = "Reciever";

    const char *cMessage = "MailCore 이용하여 SMTP 통해 메일을 보내는 기능을 테스트합니다.";

    const char *cSubject = "메일 전송 성능 테스트";

    

    NSString *messageStr = [NSString stringWithCString:cMessage encoding:NSUTF8StringEncoding];


    

    DLog(@"[dataStrArr objectAtIndex:1] = %@\n", [dataStrArr objectAtIndex:1]);

    DLog(@"cMessage = %s\n", cMessage);

    printf("printf : cMessage = %s\n", cMessage);

    DLog(@"[[dataStrArr objectAtIndex:1] UTF8String] = %s\n", [[dataStrArr objectAtIndex:1] UTF8String]);

    DLog(@"[NSString stringWithCString:cMessage encoding:NSUTF8StringEncoding] = %@\n", [NSString stringWithCString:cMessage encoding:NSUTF8StringEncoding]);

    


// 보내는 메일 주소와 받는 메일 주소는 CTCoreAddress라는 클래스 인스턴스의 NSSet 형식으로 넣어줍니다.

// 주소가 하나라도 이렇게 넣어야 합니다.

    NSArray *senderArr = [[NSUserDefaults standardUserDefaultsarrayForKey:A_SENDER_ADDRESS_E];

    NSMutableArray *senderEmailList = [[NSMutableArray allocinit];

    if (senderArr) {

        for (int i = 0; i < [senderArr count]; i++) {

            NSArray *smtp_account = [(NSString *)[senderArr objectAtIndex:i] componentsSeparatedByString:@"|"];

            CTCoreAddress *coreAddress = [CTCoreAddress addressWithName:[NSString stringWithCString:sNameencoding:NSUTF8StringEncodingemail:[smtp_account objectAtIndex:0]];

            [senderEmailList addObject:coreAddress];

        }

    }

    NSSet *fromSet = [NSSet setWithArray:senderEmailList];

    [senderEmailList release];

    

    NSArray *recieverArr = [[NSUserDefaults standardUserDefaultsarrayForKey:A_RECIEVER_ADDRESS_E];

    NSMutableArray *recieverEmailList = [[NSMutableArray allocinit];

    if (recieverArr) {

        for (int i = 0; i < [recieverArr count]; i++) {

            CTCoreAddress *coreAddress = [CTCoreAddress addressWithName:[NSString stringWithCString:rNameencoding:NSUTF8StringEncodingemail:[recieverArr objectAtIndex:i]];

            [recieverEmailList addObject:coreAddress];

        }

    }

    NSSet *toSet = [NSSet setWithArray:recieverEmailList];

    [recieverEmailList release];

    

    [coreMessage setTo:toSet];

    [coreMessage setFrom:fromSet];


    

    NSString *body = [NSString stringWithFormat:@"%@%@", [dataStrArr objectAtIndex:1], [dataStrArrobjectAtIndex:1]];

    

    [coreMessage setBody:body];

    [coreMessage setSubject:[dataStrArr objectAtIndex:0]];

    

// 첨부파일 처리하는 부분인데 첨부가 없으면 무시하셔도 됩니다.

    NSData *attData;

    if (![[dataStrArr objectAtIndex:3isEqualToString:@"N"]) {

        if ([COMFileManager isFileExistInDocument:@"attachFileList.plist"]) {

            NSMutableDictionary *attachFileList = [COMFileManager getDataFromDocument:FD_TYPE_MUTABLEDICTIONARY fromFile:@"attachFileList.plist"];

            attData = [attachFileList objectForKey:[dataStrArr objectAtIndex:2]];

            _attachSize = [attData length];

            

            NSString *contentType = @"";

            NSArray *extArr = [[dataStrArr objectAtIndex:2componentsSeparatedByString:@"."];

            

            if ([[extArr objectAtIndex:1compare:@"jpg" options:NSCaseInsensitiveSearch] == NSOrderedSame) {

                contentType = @"image/jpeg";

            } else if ([[extArr objectAtIndex:1compare:@"txt" options:NSCaseInsensitiveSearch] ==NSOrderedSame) {

                contentType = @"text/plain";//@"application/octet-stream";

            } else if ([[extArr objectAtIndex:1compare:@"mp4" options:NSCaseInsensitiveSearch] ==NSOrderedSame)  {

                contentType = @"video/mp4";

            } else if ([[extArr objectAtIndex:1compare:@"mp3" options:NSCaseInsensitiveSearch] ==NSOrderedSame)  {

                contentType = @"audio/mpeg";

            } else {

                contentType = @"application/octet-stream";

            }

            

            CTCoreAttachment *coreAttach = [[CTCoreAttachment allocinitWithData:[attachFileList objectForKey:[dataStrArr objectAtIndex:2]]

                                                                      contentType:contentType

                                                                         filename:[dataStrArr objectAtIndex:2]];

            

            [coreMessage addAttachment:coreAttach];

            [coreAttach release];

        }

    }


// 실제로 메일을 전송하는 부분입니다. 이 메서드를 호출하면 메일 바로 나갑니다. 아래 설정은 Gmail의 SMTP 설정입니다.

    [CTSMTPConnection sendMessage:coreMessageserver:SMTP_SERVER username:self.smtp_account_id password:self.smtp_account_pass port:25 useTLS:YES useAuth:YES];


    [coreMessage release];


    

}





※ 메일 받기


 

- (void) getPOP3List {

    DLog(@"getPOP3List");


    

    CTCoreAccount *coreAccount = [[CTCoreAccount allocinit];

    if (![coreAccount isConnected]) {


        // 실제로 메일은 받는 메서드. 리턴값으로는 BASE64로 인코딩된 첨부파일을 포함한 NSString형이 나옵니다. 이렇게 리턴된 메일 메시지는 아직 파싱이 안된 상태이고 이 메일 메시지를 파싱하는 클래스도 별도로 구현을 했는데 좀 허접합니다. 요 것도 소스 같이 올리겠습니다. 역시 계정은 Gmail 계정입니다.

        NSString *mailMessage = [coreAccountconnectToPOP3Server:POP3_SERVER port:POP3_TLS_PORTconnectionType:CONNECTION_TYPE_TLS authType:POP3_AUTH_TYPE_SASL_PLAINlogin:self.smtp_account_id password:self.smtp_account_pass];

               

       

        // 메일을 파싱하는 부분입니다. MailCore쪽 API를 완전히 파악 못해서 수신된 메일을 파싱하는 기능이 있는지 모르겠습니다. 우선 급한대로 대충 만들어 사용을 했습니다. 아래 코드는 첨부파일이 있을 경우 첨부파일을 추출하는 코드입니다.

        COMMailParser *mailParser = [[COMMailParser allocinitWithMail:mailMessage];

        NSData *attachData = [mailParser getFile];

        

        if (attachData) {

            _attachSize = [attachData length];

            NSString *contentType = [mailParser getAttachContentType];

        }

    }

    

    if (_attachSize < 1000.0f) {

        [self.itemReport addObject:[NSString stringWithFormat:@"%d b"_attachSize]];

    } else {

        [self.itemReport addObject:[NSString stringWithFormat:@"%d Kb"_attachSize / 1000]];

    }


}




참고로 메일파서쪽은 COMMailPaerser를 사용하시면 되구요. 나머지 파일들은 전부 외부 라이브러리들입니다.

그리고 파싱하는데 정규표현식을 사용하였더라면 좀 더 깔끔했을텐데 정규표현식에 좀 익숙하지 않아 그냥 기본 API의

문자열 처리 함수들을 이용해서 자르고 붙였습니다. 이 부분도 좀 더 깔끔하게 수정해주실 분이 계시면 좋겠네요...^^;;;



애구...글이 엄청 길어졌네요.

암튼 필요하신 분은 유용하게 쓰시길 바라겠구요.

제가 올리는 글은 언제나 그렇듯 풍부한(?) 오류가 숨어있을 수 있으니 그런 부분을 발견하시는 분들은

예쁘게 수정하셔서 재배포해주시기를 부탁드립니다...^^


아울러 제가 질문드린 내용...꼭 좀 답변 부탁드리겠습니다...ㅠ. ㅠ

블로그 이미지

마즈다

이제 반백이 되었지만 아직도 꿈을 좇고 있습니다. 그래서 그 꿈에 다가가기 위한 단편들을 하나 둘 씩 모아가고 있지요. 이 곳에 그 단편들이 모일 겁니다...^^

댓글을 달아 주세요