Ruby Mail gem, how to script mail messages - ruby

I have testmail.rb on a CENTOS 5 VM with SELinux permissive and IPtables off:
require 'rubygems'
require 'mail'
options = { :address => "mail.domain.com",
:port => 466,
:domain => 'otherdomain.com',
:user_name => 'somedude#domain.com',
:password => 'topsecret',
:authentication => 'plain',
:enable_starttls_auto => true }
Mail.defaults do
delivery_method :smtp, options
end
mail = Mail.new do
from 'somedude#otherdomain.com'
to 'admin#domain.com'
subject 'This is a test email'
body File.read('body.txt')
end
puts mail.to_s
The result when the script is run is this:
Date: Tue, 30 Nov 2010 12:12:58 -0500
From: somedude#otherdomain.com
To: admin#domain.com
Message-ID: <4cf5309a2f074_284015c5c4de91b8270b2#apvdbs03.3rdomain.local.mail>
Subject: This is a test email
Mime-Version: 1.0
Content-Type: text/plain;
charset=UTF-8
Content-Transfer-Encoding: 7bit
test!
"test!" is the content of body.txt.
No email ever reaches the sent to account. The smtp settings we got from the sent to domain admin. I used telnet to successfully send an email to the domain on the unencrypted port (25) but got no response from the encrypted port (466), possibly because my telnet session was unencrypted?
What are some ways I can see what's going on during the script execution to troubleshoot?
Update:
Tried redirecting: > log.log 2>&1, but that didn't provide any additional info.

You're missing the line to actually send. Try adding
mail.deliver!
to the end of your script.

Related

understanding ruby kEND

So i'm trying to send an email , and i believe i'm doing almost everything correctly here
#!/usr/bin/ruby
require 'rubygems'
require 'mail'
Mail.defaults do
delivery_method :smtp, address: "localhost", port: 11025
# smtp 'localhost', 11025 # '10.11.5.164' # Port 25 defult
end
mail = Mail.new do
from 'me#mydomain.net'
to 'someone#herdomain.net'
subject 'TEST'
body "here the body"
add_file :filename => 'attachment.html', :content => File.read('/tmp/attachment.html')
end
mail.deliver!
But i get:
/home/username/personal/ruby/emails/email.rb:7: syntax error, unexpected ':', expecting kEND
delivery_method :smtp, address: "localhost", port: 11025
^
/home/username/personal/ruby/emails/email.rb:7: syntax error, unexpected ',', expecting kEND
delivery_method :smtp, address: "localhost", port: 11025
Any advise? i really cant figure out what i'm doing wrong here since the official Mail documentation points out that the arguments should be colon separated.
I'm using ruby 1.9.3
Thx
It seems you are using old version of Ruby (probably 1.8?).
The symbol_name: value syntax for hash key value pairs is introduced in 1.9. Before then, say in Ruby 1.8, you need to write :symbol_name => value.
delivery_method :smtp, :address => "localhost", :port => 11025
Just like what you have written in your later code.

send email to multiple recipients using net/smtp

I have this code:
require "net/smtp"
MAIL_SERVER = "xxx.ad.xxx.net"
def lib_sending_report(email_hash)
# define message body
message = <<"MESSAGE_END"
From: <#{email_hash[:sender]}>
To: <#{email_hash[:recipients]}>
MIME-Version: 1.0
Content-type: text/html
Subject: #{email_hash[:subject]}
<p>Hi All,</p>
<p>We've just executed a round of load test.</p>
<p>Regards</p>
MESSAGE_END
Net::SMTP.start(MAIL_SERVER) do |smtp|
smtp.send_message message, email_hash[:sender], email_hash[:recipients]
end
end
test = ""
lib_sending_report( {:sender => "abc#xxx.com",
:recipients => "abc#xxxx.com",
:subject => "Load.Test.Report.of.#{test}"} )
When I change :recipients => "abc#xxxx.com" to :recipients => "abc#xxxx.com;efg#xxx.com", it gives me this error:
501 5.5.4 Invalid Address (Net::SMTPSyntaxError)
I can successfully send email when :recipients => "abc#xxxx.com" just have one recipient.
Where am I wrong? It seems that the separator(semicolon) I used is wrong.
I tried to use comma instead of semicolon, but it didn't work
Net::SMTP's send_message takes an array of "To:" address strings.
Per the documentation:
to_addr is a String or Strings or Array of Strings, representing the destination mail address or addresses.
This example from the documentation shows how:
Net::SMTP.start('smtp.example.com') do |smtp|
smtp.send_message msgstr,
'from#example.com',
['dest#example.com', 'dest2#example.com']
end

How to capture HTTP full headers with watir

I need to capture HTTP response coming after the request made.
I have tried with "net/http" gem but it is not giving me full response header.
the code I have tried is
uri = URI("http:/example.com")
res = Net::HTTP.get_response(uri)
res.to_hash
I am getting some response headers but not full headers, I have checked the same request in firebug and it is giving some extra headers what I am getting by my code
Can any one help me out for this to get full HTTP response headers, or any trick to do that by invoking browser.
Maybe this would help: WebDriver: Y U NO HAVE HTTP Status Codes?!
Try this:
uri = URI("http:/example.com")
res = Net::HTTP.get_response(uri)
res.header.to_hash
If you want to get header information, watir is probably the wrong library for you. What problem are you trying to solve?
Not a full answer but more in your direction :)
Impossible using Webdriver (see http://jimevansmusic.blogspot.nl/2012/07/webdriver-y-u-no-have-http-status-codes.html).
Possible solutions:
Use Selenium::Client
Use a proxy
Solution 1 (Selenium::Client):
You can do it using Selenium (also used by Watir Webdriver).
Check here: http://blog.testingbot.com/2011/12/21/capture-network-traffic-with-selenium
require "rubygems"
gem "selenium-client"
require "selenium/client"
gem 'test-unit'
require 'test/unit'
# since this code comes from their site (should not be needed)
gem "testingbot"
require "testingbot"
class ExampleTest < TestingBot::TestCase
attr_reader :browser
def setup
#browser = Selenium::Client::Driver.new \
:host => "hub.testingbot.com",
:port => 4444,
:browser => "firefox",
:version => "8",
:platform => "WINDOWS",
:url => "http://www.google.com",
:timeout_in_second => 60
browser.start_new_browser_session(:captureNetworkTraffic => true)
end
def teardown
browser.close_current_browser_session
end
def test_command
browser.open "/"
p browser.browser_network_traffic
end
end
According to the article this will open Google in Firefox 8 and return the network traffic. An example of a response would be:
"403 GET http://localhost:5555/favicon.ico1333 bytes 94ms
(2011-12-21T15:53:06.352+0100 - 2011-12-21T15:53:06.446+0100
Request Headers - Host => localhost:5555 -
User-Agent => Mozilla/5.0 (Windows NT 6.1; WOW64; rv:8.0.1) Gecko/20100101
Firefox/8.0.1 - Accept => image/png,image/*;q=0.8,*/*;q=0.5 -
Accept-Language => en-us,en;q=0.5 - Accept-Encoding => gzip, deflate - Accept-Charset => ISO-8859-1,utf-8;q=0.7,*;q=0.7 -
Proxy-Connection => keep-aliveResponse Headers - Date => Wed, 21 Dec 2011 14:53:06 GMT -
Server => Jetty/5.1.x (Windows 7/6.1 x86 java/1.6.0_26 - Content-Type => text/html -
Content-Length => 1333 - Via => 1.1 (jetty)
Solution 2 (Proxy):
Check http://bmp.lightbody.net/ together with https://github.com/jarib/browsermob-proxy-rb.

How to send a binary file via Pony?

I use below function to create a hash of the whole content of a directory so I can send all files as attachments.
def get_attachments_from_directory(dir)
attachment_to_send = Hash.new
Dir[dir.gsub("\\","/")+"/*"].each {|file|
file_to_send = File.read(file)
#file_to_send = File.read(file, :binmode => true)
attachment_to_send[File.basename(file)]=file_to_send
}
return attachment_to_send
end
and then I use below function to send the attachments out
def email_it(body, subject, to, from, attachment_to_send)
$smtp = 'mail.com'
$smtp_port = 25
Pony.mail(
:to => to,
:from => from,
:subject => subject,
:body => Nokogiri::HTML(body).text,
:html_body => body
:attachments => attachment_to_send,
:via => :smtp,
:via_options => {
:address => $smtp,
:port => $smtp_port,
:enable_starttls_auto => false
}
)
end
There are two files in my testing directory: .log and .png. Both of them are sent and received but .png is corrupted. gmail said that the image file cannot be displayed because it contains errors. The file name of .png file is correct in my gmail account. The file size is wrong. Much much smaller.
Show original in gmail gives me
----==_mimepart_4fd9515347359_fc1e853c88342d
Date: Thu, 14 Jun 2012 12:49:55 +1000
Mime-Version: 1.0
Content-Type: image/png;
charset=UTF-8;
filename="error_when_time_out - login at 2012-06-14 12.48.55.png"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="error_when_time_out - login at 2012-06-14 12.48.55.png"
Content-ID: <4fd95153648c7_fc1e853c883518#RATionalxp.mail>
iVBORwq/XNErlnbxOOrmtdDZDYaMWm16lTatQptSpk4t12RW6HNq6IJGvvyB
sabbUovDe5+loc9U3yPX9Yr1vWJDv9Q4KNcPydUDQnkfV9LNFrTTOc2GrEZd
Rr0uo06fUUdn1jOZ9RxRnZBZJ2bXG3M4yoTplFqeWJFGFoVBjDanha5JoWOM
bx3hi0aTQPSQNcikNoMVeYrndSi9YeVl1jxLr07oNrrn11F1kv3AeL9C8Mpi
bkTrjvku73RaeOP6/KvXVv5yzfC6vfCqHf/H64Y/XNf//obujzf0f7lp+PMt
... it continues ....
Xvjq8X//p/Ocdy68s2/DZ//5/Muvf/rvt319XzQf8p9J+7wpSTTguXYPo3Dy
TYiIaNAvYXs5ir9gv4akEz5MOO6DxGPf150oPfApIe6Yu5SVblRBYgL1TrWq
QqWsUnFag5rYTagbCD4lJCgO2hYdpGzQteqR9NCgo3ZTmh0=
----==_mimepart_4fd9515347359_fc1e853c88342d--
inspect of the hash outputs
{"error_when_time_out - login at 2012-06-14 12.50.12.png"=>"\211PNG\n\277\\\321
+\226v\3618\352\346\265\320\331\r\206\214Zmz\2256\255B\233R\246N-\327dV\350sj\35
0\202F\276\374\201\261\246\333R\213\303{\237\245\241\317T\337#\327\365\212\365\2
75bC\277\3248(\327\017\311\325\003By\037W\322\315\026\264\3239\315\206\254F]F\27
5.\243N\237QGg\3263\231\365\034Q\235\220Y'f\327\es8\312\204\351\224Z\236X\221F\0
26\205A\2146\247\205\256I\241c\214o\035\341\213F\223#\364\2205\310\2446\203\025y
If I try to read the file with #file_to_send = File.read(file, :binmode => true)
I get an error: TypeError - can't convert Hash into Integer:
ruby 1.8.7 (2010-08-16 patchlevel 302) [i386-mingw32]
mime-types (1.16)
pony (1.3)
The conventional way to read binary data without any CR+LF translation is:
File.open(file, 'rb').read
Ruby 1.9 introduces a few new ways to do this that you might be inadvertently trying in your 1.8.7 environment. The second argument to read is the number of bytes you want to read, not the mode of the file.
Be sure to read the documentation on any method you're unfamiliar with. Sometimes things aren't quite what you'd expect.

Attempt at authenticated SMTP in Ruby

I've looked at all the SMTP ruby-docs and can't figure out where I'm going wrong:
def send(username, password, data, toAddress, fromAddress)
smtp = Net::SMTP.new('my.smtp.host', 25)
smtp.start('thisisunimportant', username, password, "plain") do |sender|
sender.send_message(data, fromAddress, toAddress)
end
end
send(user, pass, rcpt, "Hey!")
Gives an unexpected kind of error:
/usr/lib/ruby/1.9.1/net/smtp.rb:725:in authenticate': wrong number of arguments (3 for 4) (ArgumentError)
from /usr/lib/ruby/1.9.1/net/smtp.rb:566:indo_start'
from /usr/lib/ruby/1.9.1/net/smtp.rb:531:in start'
from gmx_pop.rb:24:insend'
from gmx_pop.rb:30:in `'
I've tried kicking my computer a couple times but the problem persists.
Here's a description of the Net::SMTP#start call:
http://ruby-doc.org/stdlib-1.9.1/libdoc/net/smtp/rdoc/Net/SMTP.html#method-i-start
the page mentions that you can just do SMTP.start to do everything at once.
Look like you are missing the port parameter. Try port 587 for secure authentication, if that doesn't work, port 25. (check the tutorial mentioned below)
Your call should look like this:
message_body = <<END_OF_EMAIL
From: Your Name <your.name#gmail.com>
To: Other Email <other.email#somewhere.com>
Subject: text message
This is a test message.
END_OF_EMAIL
server = 'smtp.gmail.com'
mail_from_domain = 'gmail.com'
port = 587 # or 25 - double check with your provider
username = 'your.name#gmail.com'
password = 'your_password'
smtp = Net::SMTP.new(server, port)
smtp.enable_starttls_auto
smtp.start(server,username,password, :plain)
smtp.send_message(message_body, fromAddress, toAddress) # see note below!
Important:
Please note that you need to add To: , From: , Subject: headers to your message_body!
the Message-Id: and Date: headers will be added by your SMTP server
Check also:
Tutorial : http://www.java-samples.com/showtutorial.php?tutorialid=1121
the source code for Net::SMTP under ~/.rvm/src/ruby-1.9.1*/lib/net/smtp.rb
(Ruby) Getting Net::SMTP working with Gmail...?
Another way to send emails from Ruby:
You can use the ActionMailer gem from Rails to send emails from Ruby (without Rails).
At first this seems like overkill, but it makes it much easier, because you don't have to format the message body with To: , From: , Subject: , Date: , Message-Id: Headers.
# usage:
# include Email
#
# TEXT EMAIL :
# send_text_email( 'sender#somewhere.com', 'sender#somewhere.com,receiver#other.com', 'test subject', 'some body text' )
# HTML EMAIL :
# send_html_email( 'sender#somewhere.com', 'sender#somewhere.com,receiver#other.com', 'test subject', '<html><body><h1>some title</h1>some body text</body></html>' )
require 'action_mailer'
# ActionMailer::Base.sendmail_settings = {
# :address => "Localhost",
# :port => 25,
# :domain => "yourdomain.com"
# }
ActionMailer::Base.smtp_settings = { # if you're using GMail
:address => 'smtp.gmail.com',
:port => 587,
:domain => 'gmail.com',
:user_name => "your-username#gmail.com"
:password => "your-password"
:authentication => "plain",
:enable_starttls_auto => true
}
class SimpleMailer < ActionMailer::Base
def simple_email(the_sender, the_recepients, the_subject, the_body , contenttype = nil)
from the_sender
recipients the_recepients
subject the_subject
content_type contenttype == 'html' ? 'text/html' : 'text/plain'
body the_body
end
end
# see http://guides.rails.info/action_mailer_basics.html
# for explanation of dynamic ActionMailer deliver_* methods.. paragraph 2.2
module Email
# call this with a message body formatted as plain text
#
def send_text_email( sender, recepients, subject, body)
SimpleMailer.deliver_simple_email( sender , recepients , subject , body)
end
# call this with an HTML formatted message body
#
def send_html_email( sender, recepients, subject, body)
SimpleMailer.deliver_simple_email( sender , recepients , subject , body, 'html')
end
endsubject , body, 'html')
end
end
e.g. the code above works if you want to use Gmail's SMTP server to send email via your Gmail account.. Other SMTP servers may need other values for :port, :authentication and :enable_starttls_auto depending on the SMTP server setup
Try this code
Net::SMTP.smtp.start('my.smtp.host', 25, 'mail.from.domain', username, password, :plain) do |smtp|
smtp.send_message data, fromAddress, toAddress
end

Resources