Forum: Ruby Why does tmail stop my CGI script form working?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Fd22ee3cfc7dac283ce8e451af324f7d?d=identicon&s=25 Chad Perrin (Guest)
on 2008-11-17 05:09
(Received via mailing list)
I decided to try TMail for the back end of a new contact page on a
website of mine.  Unfortunately, it doesn't seem to want to work with
me.

If I don't include a line like:
  puts "Content-Type: text/html\n\n"

or like:
  puts "Content-Type: text/plain\n\n"

. . . it fails with a 500 error in the browser.

If that line comes after this line:
  require 'tmail'

. . . I get the same 500 error.

If I put it before the require 'tmail' line, however, I get a blank page
with no error messages, but no email gets sent.

If I run the script from the shell (logged in on the server), it sends
email just fine, regardless of whether that puts line is before or after
the require 'tmail' line.  Using print instead of puts doesn't seem to
make any difference, either.

Even if I have the puts line before the require 'tmail' line, no puts
lines after the require line give me any output in the browser.  If I
add
another puts line after the first, before the require line, it'll print
whatever I tell it to in the browser, though.

So, basically, the script just seems to be broken from the moment I
require the TMail library, but it breaks "silently" so I don't get any
errors -- but everything up to that point seems to work just fine
(including other require statements, before or after the content type
line).

What am I doing wrong?
5a837592409354297424994e8d62f722?d=identicon&s=25 Ryan Davis (Guest)
on 2008-11-17 05:20
(Received via mailing list)
On Nov 16, 2008, at 20:05 , Chad Perrin wrote:

> So, basically, the script just seems to be broken from the moment I
> require the TMail library, but it breaks "silently" so I don't get any
> errors -- but everything up to that point seems to work just fine
> (including other require statements, before or after the content type
> line).

what does the web server's error log say? I doubt it dies silently.
you're prolly just not looking in the right spot.
Fd22ee3cfc7dac283ce8e451af324f7d?d=identicon&s=25 Chad Perrin (Guest)
on 2008-11-17 05:48
(Received via mailing list)
On Mon, Nov 17, 2008 at 01:16:25PM +0900, Ryan Davis wrote:
> you're prolly just not looking in the right spot.
I guess I should have been clearer:

It fails without any error that shows up in the browser.  Since it's
shared hosting, and I'm unable to even *see* an Apache log anywhere, I
figure I must not have direct access to the web server logs.

I've tried wrapping the require statement in some exception handling
code, too, and that doesn't seem to give me anything useful either.
Fd22ee3cfc7dac283ce8e451af324f7d?d=identicon&s=25 Chad Perrin (Guest)
on 2008-11-17 06:10
(Received via mailing list)
On Mon, Nov 17, 2008 at 01:45:05PM +0900, Chad Perrin wrote:
> > what does the web server's error log say? I doubt it dies silently.
> > you're prolly just not looking in the right spot.
>
> I guess I should have been clearer:
>
> It fails without any error that shows up in the browser.  Since it's
> shared hosting, and I'm unable to even *see* an Apache log anywhere, I
> figure I must not have direct access to the web server logs.
>
> I've tried wrapping the require statement in some exception handling
> code, too, and that doesn't seem to give me anything useful either.

Whoops -- I had a typo in my exception handling code.  I've fixed it, so
it looks like this:

    begin
      require 'tmail'
    rescue Exception => e
      puts "#{e.class} : #{e}"
    end

. . . and the output in the browser now looks like this:

    LoadError : no such file to load -- tmail

. . . but, as I said before, it works from the shell, so I know tmail is
on the system and accessible.
6d3c187a8b3ef53b08e3e7e8572c4fea?d=identicon&s=25 Jeremy McAnally (Guest)
on 2008-11-17 06:27
(Received via mailing list)
What user is the script running as?  The environment may not be setup
properly and therefore unable to find gems etc.

--Jeremy

On Sun, Nov 16, 2008 at 11:06 PM, Chad Perrin <perrin@apotheon.com>
wrote:
>> >
>> code, too, and that doesn't seem to give me anything useful either.
> . . . and the output in the browser now looks like this:
>
--
http://jeremymcanally.com/
http://entp.com/
http://omgbloglol.com

My books:
http://manning.com/mcanally/
http://humblelittlerubybook.com/ (FREE!)
Fd22ee3cfc7dac283ce8e451af324f7d?d=identicon&s=25 Chad Perrin (Guest)
on 2008-11-17 06:32
(Received via mailing list)
On Mon, Nov 17, 2008 at 02:23:24PM +0900, Jeremy McAnally wrote:
> What user is the script running as?  The environment may not be setup
> properly and therefore unable to find gems etc.

It's running as the same user both from the shell (where it works) and
the browser (where it doesn't).  Also, it doesn't seem to have any
problems with other gems I `require`.
5a837592409354297424994e8d62f722?d=identicon&s=25 Ryan Davis (Guest)
on 2008-11-17 08:43
(Received via mailing list)
On Nov 16, 2008, at 21:06 , Chad Perrin wrote:

>    begin
>      require 'tmail'
>    rescue Exception => e
>      puts "#{e.class} : #{e}"
>    end
>
> . . . and the output in the browser now looks like this:
>
>    LoadError : no such file to load -- tmail

possibilities:

1) multiple ruby installs, webserver is using something different.
2) RUBYOPT
3) private gems?

Try this:

% env -i $SHELL --norc
% ruby myscript.cgi < /dev/null

cause that is roughly all the web browser is gonna do.
Fd22ee3cfc7dac283ce8e451af324f7d?d=identicon&s=25 Chad Perrin (Guest)
on 2008-11-17 10:53
(Received via mailing list)
Unable to get tmail working properly on my shared hosting account, I
decided to take a whack at using the command line `mail` program instead
of tmail and net/smtp.  I'd appreciate any commentary that might help me
fix this up, in case of bugs or security concerns.  The end result looks
somewhat like this:

    #!/usr/bin/env ruby
    require 'rubygems'
    require 'cgi'

    cgi = CGI.new
    print "Content-Type: text/html\n\n"

    args = cgi.params

    args.each_key do |k|
      args[k] = args[k].to_s.gsub(/"/, "''")
    end

    body_c = "

      name:  #{args['realname']}
      email: #{args['email']}
      tel.:  #{args['telephone']}

    #{args['comments']}
    "


    sub_c =     "AL Contact Form: #{args['subject']}"
    to_c =      'user@example.com'

    `echo "#{body_c}" | mail -s '#{sub_c}' #{to_c}`

    puts '<meta http-equiv="refresh"
content="0;URL=http://example.com/contact" />'

Obviously, "example.com" isn't the real domain name, and "user" isn't
the
actual user name.

I'm sure you'll notice the quote-replacement code.  Nothing else comes
to
mind that'd constitute a problematic character to send to the shell, but
if you know of any others I'd like to hear about it.  I looked around
for
a string sanitizer appropriate to my needs here, but didn't find
anything
in the standard library or core language, and if I start adding gems I'm
going to end up with the same problem I had trying to get tmail and
rmail
to work (yeah, I tried rmail too -- same problem).
6d3c187a8b3ef53b08e3e7e8572c4fea?d=identicon&s=25 Jeremy McAnally (Guest)
on 2008-11-17 17:24
(Received via mailing list)
Why not try mailfactory if you're just sending e-mail?  If it's just
tmail screwing up.  I thought perhaps you were parsing e-mail or
something.

--Jeremy

On Mon, Nov 17, 2008 at 3:49 AM, Chad Perrin <perrin@apotheon.com>
wrote:
>    cgi = CGI.new
>      name:  #{args['realname']}
>    `echo "#{body_c}" | mail -s '#{sub_c}' #{to_c}`
> in the standard library or core language, and if I start adding gems I'm
> going to end up with the same problem I had trying to get tmail and rmail
> to work (yeah, I tried rmail too -- same problem).
>
> --
> Chad Perrin [ content licensed PDL: http://pdl.apotheon.org ]
> Quoth Thomas McCauley: "The measure of a man's real character is what he
> would do if he knew he would never be found out."
>



--
http://jeremymcanally.com/
http://entp.com/
http://omgbloglol.com

My books:
http://manning.com/mcanally/
http://humblelittlerubybook.com/ (FREE!)
Fd22ee3cfc7dac283ce8e451af324f7d?d=identicon&s=25 Chad Perrin (Guest)
on 2008-11-17 18:44
(Received via mailing list)
On Tue, Nov 18, 2008 at 01:20:16AM +0900, Jeremy McAnally wrote:
> Why not try mailfactory if you're just sending e-mail?  If it's just
> tmail screwing up.  I thought perhaps you were parsing e-mail or
> something.

The problem actually appears to be one of something on the server being
misconfigured so that I cannot properly install and `require` gems.

Also . . . as someone pointed out to me off-list, I forgot to change a
set of single quotes in the `mail` command into double quotes.  The line
in question should actually read:

    `echo "#{body_c}" | mail -s "#{sub_c}" #{to_c}`

. . . rather than:

    `echo "#{body_c}" | mail -s '#{sub_c}' #{to_c}`
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2008-11-17 19:51
(Received via mailing list)
On Nov 17, 2008, at 11:38 AM, Chad Perrin wrote:

> set of single quotes in the `mail` command into double quotes.  The
> line
> in question should actually read:
>
>    `echo "#{body_c}" | mail -s "#{sub_c}" #{to_c}`

I would prefer to just avoid passing the body through the shell:

   open(%Q{| mail -s "#{sub_c}" #{to_c}}, "w") { |mail| mail << body_c }

You could use mail's escapes to avoid passing the subject as well.
See the man page for details.

James Edward Gray II
Fd22ee3cfc7dac283ce8e451af324f7d?d=identicon&s=25 Chad Perrin (Guest)
on 2008-11-17 20:58
(Received via mailing list)
On Tue, Nov 18, 2008 at 03:45:37AM +0900, James Gray wrote:
> >
> >Also . . . as someone pointed out to me off-list, I forgot to change a
> >set of single quotes in the `mail` command into double quotes.  The
> >line
> >in question should actually read:
> >
> >   `echo "#{body_c}" | mail -s "#{sub_c}" #{to_c}`
>
> I would prefer to just avoid passing the body through the shell:
>
>   open(%Q{| mail -s "#{sub_c}" #{to_c}}, "w") { |mail| mail << body_c }

That's an excellent point, and I wish I had thought of it.  I took your
advice.  The relevant code now looks like this:

    sent = open( %Q{| mail -s "#{sub_c}" #{to_c} }, 'w' ) do |msg|
      msg << body_c
    end

. . . and the sub_c variable just contains a non-interpolated string
with
nothing but letters and spaces in it.  Since the to_c variable was
already just a non-interpolated string I defined within the script, I
think this means I'm no longer in need of input sanitizing.  I think.

>
> You could use mail's escapes to avoid passing the subject as well.
> See the man page for details.

I pored over the man page for a little while, and didn't catch on to
what
you meant by this.  The closest I found to it was the reference to the
~s
escape for the mail program, but I haven't figured out yet what you
meant
should be done with it if that's your point.

However . . . having a user-supplied string in the actual email subject
line isn't really a critical necessity so, for the sake of moving
forward, I just made the subject line of sent emails static and
predefined in the script, then put the user-supplied subject string
within the body of the email the same way I did with the name and
telephone number fields.

If using a block rather than an echo command eliminates the need to
sanitize the text in the message body, it looks like the problem of
input
sanitizing is solved for now, and I really appreciate your help.  Please
correct me if I'm wrong.

I'll probably put some more time into puzzling over `man mail` at a
later
date to see if I can figure out what you meant about using mail's
escapes
to avoid passing the subject to the shell.  That would surely be good to
know for the future, even if it isn't really critical to this particular
case.
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2008-11-17 21:09
(Received via mailing list)
On Nov 17, 2008, at 1:54 PM, Chad Perrin wrote:

>>> being
>> I would prefer to just avoid passing the body through the shell:
>    end
Is sent meant to contain the output?  If so, we should probably change
that code to:

   sent = open(%Q{| mail -s"#{sub_c}" #{to_c} }, "r+") do |mail|
     mail << body_c
     mail.close_write
     mail.read
   end

>> You could use mail's escapes to avoid passing the subject as well.
>> See the man page for details.
>
> I pored over the man page for a little while, and didn't catch on to
> what
> you meant by this.  The closest I found to it was the reference to
> the ~s
> escape for the mail program, but I haven't figured out yet what you
> meant
> should be done with it if that's your point.

I've never used that feature myself, but I suspect you would use it
like this:

   mail << "~s #{sub_c}\n#{body_c}"

I'm guessing though and could be wrong.  Double check me there.

James Edward Gray II
Fd22ee3cfc7dac283ce8e451af324f7d?d=identicon&s=25 Chad Perrin (Guest)
on 2008-11-17 21:14
(Received via mailing list)
On Tue, Nov 18, 2008 at 05:05:32AM +0900, James Gray wrote:
>     mail << body_c
>     mail.close_write
>     mail.read
>   end

Actually, I stuck the sent variable in there for diagnostic purposes and
just forgot to remove it before copying and pasting.


>
> I've never used that feature myself, but I suspect you would use it
> like this:
>
>   mail << "~s #{sub_c}\n#{body_c}"
>
> I'm guessing though and could be wrong.  Double check me there.

Thanks.  I'll look into that.
This topic is locked and can not be replied to.