2012-04-09 1 views
4

Ruby와 Rails를 사용하는 IMAP 클라이언트에서 작업하고 있습니다. 메시지, 편지함 등을 성공적으로 가져올 수 있습니다. 그러나 처음 가져온 후에 마지막 동기화 이후 변경된 사항을 어떻게 검색 할 수 있습니까?Ruby IMAP이 마지막 체크 이후 "변경"되었습니다.

현재 데이터베이스에 UID 및 UID 유효성 값을 저장하고이를 비교하고 적절하게 검색하고 있습니다. 이 작동하지만 삭제 된 메시지 또는 메시지 플래그 변경 등을 감지하지 못합니다.

이러한 변경 사항을 감지 할 때마다 매번 메시지를 가져와야합니까? 다른 IMAP 클라이언트가 어떻게 그렇게 빠르게 할 수 있습니까 (예 : Apple Mail 및 Postbox). 내 스크립트는 이미 거의 이메일 주소로 계정 당 10 + 초를 취하고있다 :

# select ourself as the current mailbox 
@imap_connection.examine(self.location) 

# grab all new messages and update them in the database 
# if the uid's are still valid, we will just fetch the newest UIDs 
# otherwise, we need to search when we last synced, which is slower :(
if self.uid_validity.nil? || uid_validity == self.uid_validity 
    # for some IMAP servers, if a mailbox is empty, a uid_fetch will fail, so then 
    begin 
    messages = @imap_connection.uid_fetch(uid_range, ['UID', 'RFC822', 'FLAGS']) 
    rescue 
    # gmail cries if the folder is empty 
    uids = @imap_connection.uid_search(['ALL']) 
    messages = @imap_connection.uid_fetch(uids, ['UID', 'RFC822', 'FLAGS']) unless uids.empty? 
    end 

    messages.each do |imap_message| 
    Message.create_from_imap!(imap_message, self.id) 
    end unless messages.nil? 
else 
    query = self.last_synced.nil? ? ['All'] : ['SINCE', Net::IMAP.format_datetime(self.last_synced)] 
    @imap_connection.search(query).each do |message_id| 
    imap_message = @imap_connection.fetch(message_id, ['RFC822', 'FLAGS', 'UID'])[0] 

    # don't mark the messages as read 
    #@imap_connection.store(message_id, '-FLAGS', [:Seen]) 

    Message.create_from_imap!(imap_message, self.id) 
    end 
end 

# now assume all UIDs are valid 
self.uid_validity = uid_validity 

# now remember that we just fetched all those messages 
self.last_synced = Time.now 
self.save! 
+0

가능한가요? 관련이 있지만 속지는 아닙니다. http://stackoverflow.com/questions/1084780/getting-only-new-mail-from-an-imap-server –

+0

이미 새 메시지를 가져 오는 방법을 알고 있습니다. 삭제되거나 "변경된"메시지를 가져 오는 방법이 필요합니다 ... – sethvargo

+0

메시지가 휴지통 폴더에서 제거되면 (즉, 수동 또는 30 일 후) 삭제됩니다. 다른 클라이언트에 관해서는, 나는 FETCH 1 : * [UID]를 매우 빠르게 수행하고있는 것으로 추측하고 그 세트를 비교합니다. – Roman

답변

11

빠른 깃발 변경 재 동기화 (RFC-4551)에 대한 IMAP 확장 있습니다. 이 확장을 사용하면 (일종의 타임 스탬프에 따라) 마지막 동기화 이후 변경된 모든 메시지를 검색 할 수 있습니다. 그러나이 확장 기능이 널리 지원되지는 않습니다.

IMAP 클라이언트가 동기화를 수행하는 방법을 설명하는 정보 RFC가 있습니다 (RFC-4549, 섹션 4.3). 텍스트는 다음과 같은 두 가지 명령을 실행하는 것이 좋습니다 : 첫 번째 명령은 (얼마나 많은 메일을 모른 채) 알 수없는 모든 메일에 대한 필요한 정보를 가져 오는 데 사용됩니다

tag1 UID FETCH <lastseenuid+1>:* <descriptors> 
tag2 UID FETCH 1:<lastseenuid> FLAGS 

. 두 번째 명령은 이미 본 메일의 플래그를 동기화하는 데 사용됩니다.

AFAIK이 방법은 널리 사용됩니다. 따라서 많은 IMAP 서버에는이 정보를 빠르게 제공하기위한 최적화가 포함되어 있습니다. 일반적으로 네트워크 대역폭이 제한 요소입니다.

+0

"표준 트랙"인 RFC-7162로 답변을 업데이트 할 수도 있습니다. – themihai

1

IMAP 프로토콜은 불행히도 이런 식으로 뇌사 상태입니다. IDLE은 실제로 연결된 상태에서 이러한 종류의 물건을 반환 할 수 있어야합니다. 위의 FETCH FLAGS 제안이이를 수행하는 유일한 방법입니다.

그러나주의해야 할 점은 UID가 사양별로 주어진 세션에만 유효하다는 것입니다. 일부 서버에서 유지하는 경우에도 저장하지 마십시오.

+1

이것은 매우 비싼 작업입니다. 특히받은 편지함에 10000 개의 이메일이있는 사용자의 경우 더욱 그렇습니다. 기존 메시지를 캐싱 할 수있는 방법이 있어야합니다. – sethvargo

+1

@Aaron Zinman UID는 세션마다 다릅니다. IMAP4의 동기화 사양은 폴더 내의 메시지에 대해 일정하게 유지되므로 UID를 사용하도록 강력하게 제안합니다. RFC4549 http://tools.ietf.org/html/rfc4549에서 "연결이 끊어진 클라이언트는 연결이 끊긴 상태에서 사서함에 어떤 변화가 있었는지를 알 수 없기 때문에 메시지 번호는 연결이 끊어진 클라이언트에게 유용하지 않습니다 연결이 끊어진 모든 클라이언트 작업은 UID를 사용하여 수행되어야하므로 클라이언트는 동기화 프로세스 중에 클라이언트와 서버가 동일한 메시지에 대해 말하고 있는지 확인할 수 있습니다." –

+0

@sethvargo 지금 비슷한 프로젝트를 진행 중이고 많은 이메일을 가진 사람의 가능성을 고려하면 페이지 매김이 최선의 방법 일 것입니다. 한 페이지에 10,000 개의 이메일을 표시하지 않으므로 한 페이지에 대한 새로운 메시지를 처리 ​​할 때 미리 설정된 최대 범위를 사용하여 메시지를 끌어 올 수 있습니다. 이는 RFC 4549에서 설명합니다. 플래그와 동일한 작업으로 한 번에 요청하는 플래그의 수를 제한 할 수 있습니다. – ReX357

관련 문제