Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Email with attachments?

Reply
Thread Tools

Email with attachments?

 
 
Shashank Date
Guest
Posts: n/a
 
      09-01-2003
I have searched RAA and ruby-talk (esp. [40428]) and I have
still not managed to find a simple solution to "sending email with
binary attachments" on Windows. The code given in ruby-talk
[40429] is badly mangled and I tried resurrecting it , but am not
sure about lines 37 thru 57 (if they do not get further mangled).

I get the following error:

error on sending: The remote adapter is not compatible - connect(2)

Also, does the ability to "create MIME e-mail" automatically
imply attachment functionality ? If yes, then I guess I need to
figure it out with Tmail and RubyMail.

Any suggestions?
TIA,
-- shanko


# ---------------------- line 0 --------------------------------
# File: CyOSendMimeMailSmtp.rb
# Author: Oliver Mensinger
# Version: 2002-01-22
# Status: Usable and stable
# (for simple mails incl. binary attachm.)
#
# Description:
# Create Mime mail with text and attachments and
# send it via SMTP
#
# Changes:
# 2002-01-22 After Ian reported a problem, the mail
# server address is now given to Net::SMTP::new
# instead to Net:SMTP::start
#
# Supported functions: text part, binary attachments
# read from file
# To do: html part, binary attachment given to method
# as parameter, several recipients(cc, bcc)

require "net/smtp"
require "getoptlong"

class CyOSendMimeMailSmtp
attr_accessor :text, :server,:from,:to,:subject

def initialize()
@boundary = createBoundary()
# attachments are stored in an array,
# each index is an hash see attach method
@attachments = []
@serverlocalhost = ""
@subject = "no subject"
@from = @to = @text = ""
end

# ---------------- line 37 -------------

def createBoundary()
return ["----=_CyOSendMimeMailSmtp_Part_"] +
uniqueNumber()
end

private :createBoundary

# create an unique number, length variables
def uniqueNumber()
return [
sprintf("%02X", rand(999999990000000)), # random part
sprintf("%02X", Time.new.to_i), # machine time
sprintf("%02X", $_), # process
number
sprintf("%02X", Time.new.usec()) # micro seconds of machine
]
end

private :uniqueNumber

# ---------------- line 57 -------------

# attachBinaryFile(phy_filename, real_filename)
# adds a file and converts it to base64
# phy_filename is the physical filenameincl. path) of a file that must
exist
# real_filename will be the name of the file in the mail message
# if real_filename _is not given_, it will be the physical filename
# returns true if file exists and was attached to mail, otherwise false

def attachBinaryFile(phy_filename, real_filename)
# read file into string and convert it to base64
begin
f = File.new(phy_filename);
data = f.read()
f.close()
rescue
return false
end

data = [data].pack("m*");

real_filename = phy_filename if (real_filename=="")

# the very special problem of phy_filename and real_filename:
# the physical filename could be something like
# tmp/12367672647342342,
# as an external binary file stored outside of a database, where the
# real filename is the original filename which is stored in the database
# so we take the real_filename for determining the files type

attachment = {"type" => contentType(real_filename),
"name" => File.basename(real_filename),
"data" => data }

@attachments.push(attachment)
end


def contentType(filename)
filename = File.basename(filename).downcase
return "image/jpg" if (filename =~ /\.jp(e?)g$/)
return "image/gif" if (filename =~ /\.gif$/)
return "text/html" if (filename =~ /\.htm(l?)$/)
return "text/plain" if (filename =~ /\.txt$/ )
return "application/zip" if (filename =~ /\.zip$/)
# more types?!
return "application/octet-stream"
end

private :contentType

def sendMail()

raise "mail server not specified" if(@server.length == 0)
raise "sender address not specified" if(@from.length == 0)
raise "receiver address not specified" if(@to.length == 0)

#raise "nothing to send" if((@text.length==0)&(@attachments.length==0))

smtp = Net::SMTP.new(@server)
smtp.start()
smtp.ready(@from, @to) do |wa|
wa.write("Reply-To:{@from}\r\n")
wa.write("To:{@to}\r\n")
wa.write("Subject:{@subject}\r\n")
wa.write("MIME-Version:.0\r\n")
# add multipart header if we have got attachments
if(@attachments.length)
wa.write("Content-Type: multipart/mixed;
boundary=\"#{@boundary}\"\r\n")
wa.write("\r\n")
wa.write("This is a multi-part message in MIME format.\r\n")
wa.write("\r\n")
end

# add text part if given
if(@text.length)
# add boundary if we are multiparted, otherwise just add text
if(@attachments.length)
wa.write("--#{@boundary}\r\n")
wa.write("Content-Type: text/plain; charset=\"iso-8859-1\"\r\n")
wa.write("Content-Transfer-Encoding:bit\r\n")
# we don't take care of very old mail servers with bit only
else
# if only text and no attachm. we give the encoding
wa.write("Content-Type: text/plain; charset=iso-8859-1\r\n")
wa.write("Content-Transfer-Encoding:bit\r\n")
end
wa.write("\r\n")
wa.write("#{@text}\r\n")
wa.write("\r\n")
end


# add attachments if given
if(@attachments.length)
@attachments.each do |part|
wa.write("--#{@boundary}\r\n")
wa.write("Content-Type:{part['type']};
name=\"#{part['name']}\"\r\n")
wa.write("Content-Transfer-Encoding: base64\r\n")
wa.write("Content-Disposition: attachment;
filename=\"#{part['name']}\"\r\n")
wa.write("\r\n")
wa.write("#{part['data']}") # no more need for \r\n here!
wa.write("\r\n")
end
end

# closing boundary if multiparted
wa.write("--#{@boundary}--\r\n") if(@attachments.length)
end # smtp.ready(...)
end # def sendMail()
end # class CyOSendMimeMailSmtp


if $0 == __FILE__
# example for using CyOSendMimeMailSmtp class
# require "CyOSendMimeMailSmtp.rb"

mail = CyOSendMimeMailSmtp.new()
mail.server = "pop3.everestkc.net"
mail.from = "(E-Mail Removed)"
mail.to = "(E-Mail Removed)"
mail.subject = "1st test using class CyOSendMimeMailSmtp"
mail.text = "I love Ruby!\n2nd line."

#if(!mail.attachBinaryFile("/home/cyo/ruby.jpg"))
# puts "could not attach file"
#end

begin
mail.sendMail()
rescue
puts "error on sending: #{$!}"
end

end





 
Reply With Quote
 
 
 
 
Carlos
Guest
Posts: n/a
 
      09-02-2003
> I have searched RAA and ruby-talk (esp. [40428]) and I have
> still not managed to find a simple solution to "sending email with
> binary attachments" on Windows. The code given in ruby-talk
> [40429] is badly mangled and I tried resurrecting it , but am not
> sure about lines 37 thru 57 (if they do not get further mangled).
>
> I get the following error:
>
> error on sending: The remote adapter is not compatible - connect(2)
>
> Also, does the ability to "create MIME e-mail" automatically
> imply attachment functionality ? If yes, then I guess I need to
> figure it out with Tmail and RubyMail.



I don't know what generates the error you get, but you have some bugs here:


>
> def sendMail()
>
> raise "mail server not specified" if(@server.length == 0)
> raise "sender address not specified" if(@from.length == 0)
> raise "receiver address not specified" if(@to.length == 0)
>
> #raise "nothing to send"
> if((@text.length==0)&(@attachments.length==0))
>
> smtp = Net::SMTP.new(@server)
> smtp.start()
> smtp.ready(@from, @to) do |wa|
> wa.write("Reply-To:{@from}\r\n")


^^^^^^--- should be #{@from}

> wa.write("To:{@to}\r\n")


^^^^^--- should be #{@to}

>
> wa.write("Subject:{@subject}\r\n")


^^^^^^^^^^-- #{@subject}

>
> wa.write("MIME-Version:.0\r\n")



Add the '#' and maybe will work.


 
Reply With Quote
 
 
 
 
Shashank Date
Guest
Posts: n/a
 
      09-02-2003

"Carlos" <(E-Mail Removed)> wrote in message
> > wa.write("Reply-To:{@from}\r\n")

>
> ^^^^^^--- should be #{@from}
>
> > wa.write("To:{@to}\r\n")

>
> ^^^^^--- should be #{@to}
>
> >
> > wa.write("Subject:{@subject}\r\n")

>
> ^^^^^^^^^^-- #{@subject}
>
> >
> > wa.write("MIME-Version:.0\r\n")


Thanks for pointing that out ... I corrected them and some more
minor issues and still not able to make it work. (

-- shanko


 
Reply With Quote
 
Carlos
Guest
Posts: n/a
 
      09-02-2003
> Thanks for pointing that out ... I corrected them and some more
> minor issues and still not able to make it work. (


Here is the original script, with superfluous linefeeds removed (and
different sender, etc., for testing purposes). It works for me...


require "net/smtp"
require "getoptlong"

# File: CyOSendMimeMailSmtp.rb
# Author: Oliver Mensinger
# Version: 2002-01-22
# Status: Usable and stable for simple mails (incl. binary attachm.)
#
# Description:
# Create Mime mail with text and attachments and send it via SMTP
#
# Changes:
# 2002-01-22 After Ian reported a problem, the mail server address is now given
# to Net::SMTP::new instead to Net:SMTP::start
#
# Supported functions: text part, binary attachments read from file
# To do: html part, binary attachment given to method as parameter, several recipients (cc, bcc)

class CyOSendMimeMailSmtp
attr_accessor :text
attr_accessor :server, :from, :to, :subject

def initialize()
@boundary = createBoundary()
@attachments = [] # or Array.new, attachments are stored in an array, each index is an hash (see attach method)
@server = "localhost"
@subject = "no subject"
@from = @to = @text = ""
end


def createBoundary()
return "----=_CyOSendMimeMailSmtp_Part_" + uniqueNumber()
end

private :createBoundary

# create an unique number, length variables

def uniqueNumber()
return sprintf("%02X", rand(99999999 - 10000000) + 10000000) + # random part
sprintf("%02X", Time.new.to_i) + # machine time
sprintf("%02X", $$) + # process number
sprintf("%02X", Time.new.usec()) # micro seconds of machine
end

private :uniqueNumber

# attachBinaryFile(phy_filename, real_filename = "")
# adds a file and converts it to base64
# phy_filename is the physical filename (incl. path) of a file that must exist
# real_filename will be the name of the file in the mail message
# if real_filename _is not given_, it will be the physical filename
# returns true if file exists and was attached to mail, otherwise false

def attachBinaryFile(phy_filename, real_filename = "")
# read file into string and convert it to base64
begin
f = File.new(phy_filename);
data = f.read()
f.close()
rescue
return false
end

data = [data].pack("m*");

real_filename = phy_filename if real_filename == ""

# the very special problem of phy_filename and real_filename:
# the physical filename could by something like /tmp/12367672647342342,
# as an external binary file stored outside of a database, where the
# real filename is the original filename which is stored in the database.
# so we take the real_filename for determining the files type
attachment = { "type" => contentType(real_filename), "name" => File.basename(real_filename), "data" => data }
@attachments.push(attachment)
end


def contentType(filename)
filename = File.basename(filename).downcase
if filename =~ /\.jp(e?)g$/ then return "image/jpg" end
if filename =~ /\.gif$/ then return "image/gif" end
if filename =~ /\.htm(l?)$/ then return "text/html" end
if filename =~ /\.txt$/ then return "text/plain" end
if filename =~ /\.zip$/ then return "application/zip" end
# more types?!
return "application/octet-stream"
end

private :contentType

def sendMail()
raise "mail server not specified" if @server.length == 0
raise "sender address not specified" if @from.length == 0
raise "receiver address not specified" if @to.length == 0
#raise "nothing to send" if (@text.length == 0) && (@attachments.length == 0)

smtp = Net::SMTP.new(@server)
smtp.start()
smtp.ready(@from, @to) do |wa|
wa.write("Reply-To: #{@from}\r\n")
wa.write("To: #{@to}\r\n")
wa.write("Subject: #{@subject}\r\n")
wa.write("MIME-Version: 1.0\r\n")
# add multipart header if we have got attachments
if (@attachments.length > 0)
wa.write("Content-Type: multipart/mixed; boundary=\"#{@boundary}\"\r\n")
wa.write("\r\n")
wa.write("This is a multi-part message in MIME format.\r\n")
wa.write("\r\n")
end

# add text part if given
if (@text.length > 0)
# add boundary if we are multiparted, otherwise just add text
if (@attachments.length > 0)
wa.write("--#{@boundary}\r\n")
wa.write("Content-Type: text/plain; charset=\"iso-8859-1\"\r\n")
wa.write("Content-Transfer-Encoding: 8bit\r\n") # we don't take care of very old mail servers with 7 bit only
else
# if only text and no attachm. we give the encoding
wa.write("Content-Type: text/plain; charset=iso-8859-1\r\n")
wa.write("Content-Transfer-Encoding: 8bit\r\n")
end
wa.write("\r\n")
wa.write("#{@text}\r\n")
wa.write("\r\n")
end


# add attachments if given
if (@attachments.length > 0)
@attachments.each do |part|
wa.write("--#{@boundary}\r\n")
wa.write("Content-Type: #{part['type']}; name=\"#{part['name']}\"\r\n")
wa.write("Content-Transfer-Encoding: base64\r\n")
wa.write("Content-Disposition: attachment; filename=\"#{part['name']}\"\r\n")
wa.write("\r\n")
wa.write("#{part['data']}") # no more need for \r\n here!
wa.write("\r\n")
end
end

# closing boundary if multiparted
wa.write("--#{@boundary}--\r\n") if (@attachments.length > 0)
end # smtp.ready(...)
end # def sendMail()
end # class CyOSendMimeMailSmtp


#=begin
# example for using CyOSendMimeMailSmtp class
#require "CyOSendMimeMailSmtp.rb"

mail = CyOSendMimeMailSmtp.new()
mail.server = "localhost" # localhost is also default
mail.from = "(E-Mail Removed)"
mail.to = "(E-Mail Removed)"
mail.subject = "1st test using class CyOSendMimeMailSmtp" # default is "no subject"
mail.text = "I love Ruby!\n2nd line."


if (!mail.attachBinaryFile("/home/angus/desktop0901.png"))
puts "could not attach file"
end


begin
mail.sendMail()
rescue
puts "error on sending: #{$!}"
end
#=end


 
Reply With Quote
 
Shashank Date
Guest
Posts: n/a
 
      09-02-2003

"Carlos" <(E-Mail Removed)> wrote in message
> Here is the original script, with superfluous linefeeds removed (and
> different sender, etc., for testing purposes). It works for me...


Great ! I will take your word for it ... until I figure out how to
start a SMTP server on my machine (Windows XP Pro).

[snip]

> def uniqueNumber()
> return sprintf("%02X", rand(99999999 - 10000000) + 10000000) + #

random part
> sprintf("%02X", Time.new.to_i) + # machine time
> sprintf("%02X", $$) + # process number
> sprintf("%02X", Time.new.usec()) # micro seconds of machine
> end


This was the part which I had got all messed up. Everything else seemed
to be OK (after you corrected me the first time).

[snip]

> mail = CyOSendMimeMailSmtp.new()
> mail.server = "localhost" # localhost is also default

^^^^^^^^^^^^^^^^^^^^
And this is what I am still struggling with. Any ideas are highly welcome.
Again thank you very much, Carlos !

-- shanko



 
Reply With Quote
 
Carlos
Guest
Posts: n/a
 
      09-02-2003
> > mail = CyOSendMimeMailSmtp.new()
> > mail.server = "localhost" # localhost is also default

> ^^^^^^^^^^^^^^^^^^^^
> And this is what I am still struggling with. Any ideas are highly welcome.


Just put the name of the smtp server you normally use to send mail. I guess
it should be 'mail.everestkc.net', or something like that.


 
Reply With Quote
 
Shashank Date
Guest
Posts: n/a
 
      09-04-2003

"Shashank Date" <(E-Mail Removed)> wrote in message
> That was the first thing I tried ... used "smtp.everestkc.net" but it gave
> me the following error:
> so I thought it must be something else. What do you say ?
>
> C:/ruby/lib/ruby/1.8/net/protocol.rb:188:in `on_read_timeout': socket read
> timeout (60 sec) (TimeoutError)


[snip]

I tried changing the read timeout variable @read_timeout (line 270 of
C:/ruby/lib/ruby/1.8/net/smtp.rb) to 120 (from 60) but got the same error.

Any ideas, gurus ?

TIA,
-- shanko


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Mozilla Thunderbird Email NOT capturing clicked email links... AJPDLA Firefox 4 04-12-2006 07:05 PM
Email server timing out in email script John Silver Perl 0 02-04-2005 07:47 AM
page to image image to email email to fax jason@cyberpine.com ASP .Net 3 07-27-2004 09:51 PM
Email ErrorPage to email Tee ASP .Net 0 06-23-2004 07:44 PM
HowTo:? open email client to send email Peter ASP .Net 0 07-01-2003 04:58 PM



Advertisments