Programming language/go lang

[Go lang] go-imap 깃허브 살펴보기

engine 2021. 10. 8. 13:17

IMAP4rev1 이동 작성 라이브러리

 클라이언트 및/또는 서버를 구축하는 데 사용할 수 있다.

 

client code

package main

import (
	"log"

	"github.com/emersion/go-imap/client"
	"github.com/emersion/go-imap"
)

func main() {
	log.Println("Connecting to server...")

	// Connect to server
	c, err := client.DialTLS("mail.example.org:993", nil)
	if err != nil {
		log.Fatal(err)
	}
	log.Println("Connected")

	// Don't forget to logout
	defer c.Logout()

	// Login
	if err := c.Login("username", "password"); err != nil {
		log.Fatal(err)
	}
	log.Println("Logged in")

	// List mailboxes
	mailboxes := make(chan *imap.MailboxInfo, 10)
	done := make(chan error, 1)
	go func () {
		done <- c.List("", "*", mailboxes)
	}()

	log.Println("Mailboxes:")
	for m := range mailboxes {
		log.Println("* " + m.Name)
	}

	if err := <-done; err != nil {
		log.Fatal(err)
	}

	// Select INBOX
	mbox, err := c.Select("INBOX", false)
	if err != nil {
		log.Fatal(err)
	}
	log.Println("Flags for INBOX:", mbox.Flags)

	// Get the last 4 messages
	from := uint32(1)
	to := mbox.Messages
	if mbox.Messages > 3 {
		// We're using unsigned integers here, only subtract if the result is > 0
		from = mbox.Messages - 3
	}
	seqset := new(imap.SeqSet)
	seqset.AddRange(from, to)

	messages := make(chan *imap.Message, 10)
	done = make(chan error, 1)
	go func() {
		done <- c.Fetch(seqset, []imap.FetchItem{imap.FetchEnvelope}, messages)
	}()

	log.Println("Last 4 messages:")
	for msg := range messages {
		log.Println("* " + msg.Envelope.Subject)
	}

	if err := <-done; err != nil {
		log.Fatal(err)
	}

	log.Println("Done!")

server code

package main

import (
	"log"

	"github.com/emersion/go-imap/server"
	"github.com/emersion/go-imap/backend/memory"
)

func main() {
	// Create a memory backend
	be := memory.New()

	// Create a new server
	s := server.New(be)
	s.Addr = ":1143"
	// Since we will use this server for testing only, we can allow plain text
	// authentication over unencrypted connections
	s.AllowInsecureAuth = true

	log.Println("Starting IMAP server at localhost:1143")
	if err := s.ListenAndServe(); err != nil {
		log.Fatal(err)
	}
}

Constants

const (
// 연결 상태에서 서버는 아직 인사말을 보내지 않았으며 명령을 내릴 수 없다.
    ConnectingState = 0

//인증되지 않은 상태에서 클라이언트는 대부분의 명령이 허용되기 전에 인증 자격 증명을 제공해야 한다.
//이 상태는 연결이 사전 인증되지 않은 경우 연결이 시작될 때 입력된다.
    NotAuthenticatedState ConnState = 1 << 0

// 인증된 상태에서 클라이언트는 인증되었으며 메시지에 영향을 미치는 명령이 허용되기 전에  액세스할 mailbox 선택해야 한다.
//이 상태는 사전 인증된 연결이 시작될 때, 허용 가능한 인증 자격 증명이 제공되었을 때, 
//mailbox 선택 오류 후 또는 성공적인 CLOSE 명령 후에 입력된다.
    AuthenticatedState = 1 << 1

// 선택된 상태에서 액세스할 mailbox 선택
// 이 상태는 mailbox 성공적으로 선택되었을 때 입력
    SelectedState = AuthenticatedState + 1<<2

// 로그아웃 상태에서 연결이 종료되고 있다.
//이 상태는 클라이언트 요청의 결과(LOGOUT 명령을 통해) 또는 클라이언트 또는 서버 측의 일방적인 작업의 결과로 입력될 수 있습니다.
     LogoutState = 1 << 3

    // ConnectedState는 NotAuthenticatedState, AuthenticatedState 또는 SelectedState다.
    ConnectedState = NotAuthenticatedState | AuthenticatedState | SelectedState
)
const (
    // RFC 3501에서 page 83 date-text 정의
    DateLayout = "_2-Jan-2006"
	// RFC 3501에서 page 83 date-time 정의
    DateTimeLayout = "_2-Jan-2006 15:04:05 -0700"
)

날짜 및 시간 레이아웃

Dovecot 날짜 앞에 0을 추가

Cyrus 날짜에 공백 추가

Gmail은 SEARCH 명령에 사용되는 날짜에 공백을 지원하지 않는다.

const (
    // SetFlags : 기존 플래그를 새 플래그로 교체
    SetFlags FlagsOp = "FLAGS"
    // AddFlags : 새 플래그 추가
    AddFlags = "+FLAGS"
    // RemoveFlags : 기존 플래그를 제거
    RemoveFlags = "-FLAGS"
)
const (
    // 계층의 하위 수준이 이 아래에 존재할 수 없다.
    // 이름; 현재 하위 수준이 없으며 미래에도 생성할 수 없다.
    NoInferiorsAttr = "\\Noinferiors"
    // 이 이름을 선택 가능한 mailbox로 사용할 수 없다.
    NoSelectAttr = "\\Noselect"
    // 아마도 마지막 시간 이후에 추가된 메시지를 포함할 것이다.
    // 사서함이 선택되었습니다.
    MarkedAttr = "\\Marked"
    // mailbox 마지막 시간 이후로 추가 메시지를 포함하지 않는다.
    // mailbox 선택
    UnmarkedAttr = "\\Unmarked"
)
const (
    // 사용자의 메시지 저장소에 있는 모든 메시지를 표시
    AllAttr = "\\All"
    // 메시지를 보관하는 데 사용
    ArchiveAttr = "\\Archive"
    //작성 중이지만 아직 보내지 않은 메시지
    DraftsAttr = "\\Drafts"
    // "중요"로 표시된 모든 메시지 표시
    FlaggedAttr = "\\Flagged"
    // 정크 메일로 간주되는 메시지가 보관되는 곳
    JunkAttr = "\\Junk"
    // 보낸 메시지의 복사본을 보관하는 데 사용
    SentAttr = "\\Sent"
    // 삭제되었거나 삭제 표시된 메시지를 보관하는 데 사용
   TrashAttr = "\\Trash"
)
const (
    // 사서함에 자식 사서함이 있음을 나타냄
    HasChildrenAttr = "\\HasChildren"
    // 자식 사서함이 없음을 나타냄
    HasNoChildrenAttr = "\\HasNoChildren"
)
const (
    SeenFlag     = "\\Seen"
    AnsweredFlag = "\\Answered"
    FlaggedFlag  = "\\Flagged"
    DeletedFlag  = "\\Deleted"
    DraftFlag    = "\\Draft"
    RecentFlag   = "\\Recent"
)
const (
    // 헤더를 포함하여 전체 부분을 참조
    EntireSpecifier PartSpecifier = ""
    // header of the part를 참조
    //헤더와 본문을 구분하는 최종 CRLF를 포함해야 한다.
    HeaderSpecifier = "HEADER"
    // 헤더를 생략하고 파트의 텍스트 본문을 참조
    TextSpecifier = "TEXT"
    // MIME 인터넷 메시지 본문 헤더를 참조 헤더와 본문을 구분하는 최종 CRLF를 포함해야 한다.
    MIMESpecifier = "MIME"
)
const ImportantAttr = "\\Important"
//mailbox 사용자에게 중요한 메시지가 포함되어 있다는 신호

const ImportantFlag = "$Important"
//ImportantFlag는 메시지가 사용자에게 중요할 수 있음을 알리는 메시지 플래그

const InboxName = "INBOX"
//The primary mailbox

const TryCreateFlag = "\\*"
//TryCreateFlag는 MailboxStatus.PermanentFlags의 특수 플래그
//해당 플래그를 사서함에 저장하여 새 키워드를 생성할 수 있음을 나타낸다.

Variables

var CharsetReader func(charset string, r io.Reader) (io.Reader, error)
/*CharsetReader가 nil이 아닌 경우 
제공된 charset에서 UTF-8로 변환하는 charset-conversion reader를 생성하는 함수를 정의
문자 집합은 항상 소문자 utf-8 및 us-ascii 문자 집합은 기본적으로 처리
CharsetReader의 결과 값 중 하나는 nil이 아니어야 한다.
*/
func CanonicalFlag(flag string) string {
//CanonicalFlag : 플래그의 표준 형식을 반환. 플래그는 대소문자를 구분하지 않는다.

func CanonicalMailboxName(name string) string {
//CanonicalMailboxName은 사서함 이름의 표준 형식을 반환
//사서함 이름은 백엔드 구현에 따라 대소문자를 구분하거나 구분하지 않을 수 있다.
//특수 INBOX 사서함은 대소문자를 구분하지 않는다.

func FormatAddressList(addrs []*Address) interface{} {
// 주소 목록을 필드 형식으로 지정

func FormatMailboxName(name string) interface{} {
func FormatParamList(params map[string]string) []interface{} {
func FormatStringList(list []string) (fields []interface{}) {
func IsParseError(err error) bool {
//제공된 오류가 Reader에서 생성된 구문 분석 오류인 경우 IsParseError는 true를 반환

func NewDebugWriter(local, remote io.Writer) io.Writer {
// 로컬 네트워크 활동을 로컬에 쓰고 원격 네트워크 활동을 원격에 쓰는 새 io.Writer를 만듬

func NewLockedWriter(w io.Writer) io.Writer {
//NewLockedWriter - 고루틴 Writer

func ParseNamedResp(resp Resp) (name string, fields []interface{}, ok bool) {
//ParseNamedResp는 명명된 데이터 응답을 구문 분석하려고 시도

func ParseNumber(f interface{}) (uint32, error) {
//ParseNumber는 숫자를 구문 분석

func ParseParamList(fields []interface{}) (map[string]string, error) {

func ParseString(f interface{}) (string, error) {
//ParseString은 리터럴, 인용 문자열 또는 원자인 문자열을 구문 분석

func ParseStringList(f interface{}) ([]string, error) {
//필드 목록을 문자열 목록으로 변환

type Address

type Address struct {
    // personal name(개인 이름)
    PersonalName string
    // SMTP at-domain-list(소스 경로)
    AtDomainList string
    // The mailbox name(사서함 이름)
    MailboxName string
    // The host name(호스트 이름)
    HostName string
}
func ParseAddressList(fields []interface{}) (addrs []*Address) {
//필드에서 주소 목록을 구문 분석

func (addr *Address) Address() string {
// 주소는 사서함 주소 반환(예: "foo@example.org").

func (addr *Address) Format() []interface{} {
// 주소를 필드 형식으로 지정

func (addr *Address) Parse(fields []interface{}) error {
// 필드에서 주소를 구문 분석

type BodyPartName

type BodyPartName struct {
    // specifier of the requested part(요청된 부분의 지정자)
    Specifier PartSpecifier
	// part path 부품 Parts indexes 1에서 시작
    Path []int
    // Specifier가 HEADER인 경우 NotFields 값에 따라 반환되거나 반환되지 않는 헤더 필드를 포함
    Fields []string
    // true로 설정하면 Fields는 화이트리스트 대신 필드의 블랙리스트
    NotFields bool
}
func (part *BodyPartName) Equal(other *BodyPartName) bool {
//Equal 두 개의 body part names 같은지 여부 확인

type BodySectionName

type BodySectionName struct {
    BodyPartName
	// true로 설정하면 암시적으로 \Seen 플래그를 설정하지 않는다.
    Peek bool
    // 요청된 섹션의 하위 문자열
    //첫 번째 값은 첫 번째 원하는 옥텟의 위치이고 두 번째 값은 원하는 최대 옥텟 수
     Partial []int
    // 필터링되거나 내보내지지 않은 필드를 포함
}
func ParseBodySectionName(s FetchItem) (*BodySectionName, error) {
//ParseBodySectionName : 본문 섹션 이름을 구문 분석

func (section *BodySectionName) Equal(other *BodySectionName) bool {
//Equal은 두 섹션이 동일한지 여부 확인

func (section *BodySectionName) ExtractPartial(b []byte) []byte {
//ExtractPartial : 섹션 이름에서 요청된 부분과 일치하는 지정된  bytes 하위 집합을 반환

func (section *BodySectionName) FetchItem() FetchItem {

type BodyStructure

 

type BodyStructure struct {

    // The MIME type (e.g. "text", "image")
    MIMEType string
    // The MIME subtype (e.g. "plain", "png")
    MIMESubType string
    // The MIME parameters.
    Params map[string]string

    // The Content-Id header.
    Id  string
    // The Content-Description header.
    Description string
    // The Content-Encoding header.
    Encoding string
    // The Content-Length header.
    Size uint32

    // The children parts, if multipart.
    Parts []*BodyStructure
    // The envelope, if message/rfc822.
    Envelope *Envelope
    // The body structure, if message/rfc822.
    BodyStructure *BodyStructure
    // The number of lines, if text or message/rfc822.
    Lines uint32

    // True if the body structure contains extension data.
    Extended bool

    // The Content-Disposition header field value.
    Disposition string
    // The Content-Disposition header field parameters.
    DispositionParams map[string]string
    // The Content-Language header field, if multipart.
    Language []string
    // The content URI, if multipart.
    Location []string

    // The MD5 checksum.
    MD5 string
}

https://github.com/emersion/go-imap

 

GitHub - emersion/go-imap: An IMAP library for clients and servers

:inbox_tray: An IMAP library for clients and servers - GitHub - emersion/go-imap: An IMAP library for clients and servers

github.com