After the mail server receives the email, the service pushes the notification program. Is there any way to achieve it?
1. Client polling
2. The server actively pushes.
First, let’s get familiar with the protocol for sending and receiving emails:
Net::SMTP (send email)
Net::POP3 (receive emails)
Net::IMAP (receive mail)
There are many examples of receiving emails using pop3, but receiving emails using pop3 can only get all the emails in the inbox. Tags such as whether the email has been read and cannot be obtained. Using the imap protocol avoids this embarrassment. Imap not only can obtain detailed information of an email (such as whether it has been read and whether it has been replyed), but it also allows users to change the email tag. However, there are not many email servers that support the imap protocol. I only know 21cn and gmail. The following example uses multiple contents of proxy and SSL authentication. Please refer to it.
Imap emails are all requested on demand. That is to say, when you get a Message object, there is actually no information in it. When you use the get method to obtain information in this object, such as getSubject, the Message object will revisit the mail server to get the message. Therefore, before you get all the required information, you cannot close the directory, and you cannot disconnect. If you really want to operate the Message object after closing the directory or connecting, you need to use the fetch method of the Folder object to get the required information.
1: Client polling
Here is a pop3 and imap example of polling access to get emails:
POP3 Polling:
loop do
require 'net/pop'
pop = Net::('EMAILSERVICE')
('USENAME', 'PASSWORD')
if ?
puts 'No mail.'
else
pop.each_mail do |m|
do |chunk|
p chunk
end
end
puts "#{} mails popped."
end
sleep(10)
end
imap polling:
loop do
require 'net/imap'
imap = Net::('EMAILSERVICE')
"USERNAME", "PASSWORD"
('INBOX')
(["BEFORE", "29-Oct-2014", "SINCE", "28-Oct-2014"]).each do |message_id|
envelope = (message_id, "ENVELOPE")[0].attr["ENVELOPE"]
puts "#{[0].name}: \t#{}"
end
sleep(10)
end
Two: The server actively pushes
The following implements a server active push method: ()
This is a technology between pull and Persistent TCP/IP: long polling. The principle is that every time the client requests the service, the server holds it. After a message returns or time out, it will initiate a request again and wait for the message to arrive. This mode does not require the heartbeat to keep the heartbeat, nor does it require continuous TCP occupation, and is more suitable for the push of timely messages on the page side.
SERVER = 'EMAILSERVICE'
USERNAME = 'USERNAME'
PW = 'PASSWORD'
require 'net/imap'
# Extend support for idle command. See online.
# /topic/50828
# /jem/2783772
# but that was wrong. see /opt/ruby-1.9.1-p243/lib/net/.
class Net::IMAP
def idle
cmd = "IDLE"
synchronize do
@idle_tag = generate_tag
put_string(@idle_tag + " " + cmd)
put_string(CRLF)
end
end
def say_done
cmd = "DONE"
synchronize do
put_string(cmd)
put_string(CRLF)
end
end
def await_done_confirmation
synchronize do
get_tagged_response(@idle_tag, nil)
puts 'just got confirmation'
end
end
end
class Remailer
attr_reader :imap
public
def initialize
@imap = nil
@mailer = nil
start_imap
end
def tidy
stop_imap
end
def print_pust
envelope = @(-1, "ENVELOPE")[0].attr["ENVELOPE"]
puts "From:#{[0].name}\t Subject: #{}"
end
def bounce_idle
# Bounces the idle command.
@imap.say_done
@imap.await_done_confirmation
# Do a manual check, just in case things aren't working properly.
@
end
private
def start_imap
@imap = Net::('')
@ USERNAME, PW
@ 'INBOX'
# Add handler.
@imap.add_response_handler do |resp|
if resp.kind_of?(Net::IMAP::UntaggedResponse) and == "EXISTS"
@imap.say_done
do
@imap.await_done_confirmation
print_pust
@
end
end
end
@
end
def stop_imap
@
end
end
begin
Net:: = true
r =
loop do
puts 'bouncing...'
r.bounce_idle
sleep 15*60
#Generally set to keep the long link without operation for 15 minutes
end
ensure
end