将HTML表单发布到remote.cgi-用Ruby编写?

将HTML表单发布到remote.cgi-用Ruby编写?,ruby,email,cgi,sinatra,thin,Ruby,Email,Cgi,Sinatra,Thin,我正在一个微软office live服务网站上工作。它有一个联系表,使访问者能够与业主取得联系。我想写一个Ruby脚本,它位于一个单独的服务器上,表单将发布到该服务器上。它将解析表单数据并通过电子邮件将详细信息发送到预设地址。然后,脚本应将浏览器重定向到确认页面 我有一台运行nginx和postfix的ubuntu hardy机器。Ruby已经安装,我们将了解如何使用Thin及其机架功能来处理脚本。现在到了写剧本的时候了,我画了一张空白 这是一个很长的时间,如果我记得正确的过程是这样的 读取H

我正在一个微软office live服务网站上工作。它有一个联系表,使访问者能够与业主取得联系。我想写一个Ruby脚本,它位于一个单独的服务器上,表单将发布到该服务器上。它将解析表单数据并通过电子邮件将详细信息发送到预设地址。然后,脚本应将浏览器重定向到确认页面

我有一台运行nginx和postfix的ubuntu hardy机器。Ruby已经安装,我们将了解如何使用Thin及其机架功能来处理脚本。现在到了写剧本的时候了,我画了一张空白

这是一个很长的时间,如果我记得正确的过程是这样的

  • 读取HTTP头
  • 解析参数
  • 发送电子邮件
  • 发送重定向头
从广义上讲,这个问题已经得到了回答。找出如何使用答案比预期的要复杂,我认为值得分享

第一步:

我相当突然地了解到nginx不直接支持cgi脚本。您必须使用其他一些进程来运行脚本并让nginx通过代理请求。如果我用php来做这件事(事后看来,我认为这是一个更自然的选择),我可以使用php fcgi之类的东西,并期望生活会很简单

Ruby和fcgi感到非常气馁。但是,如果我们放弃在运行时加载这些东西的理想,那么Rack可能是最直接的解决方案,Thin包含了我们所需要的一切。学习如何用它们制作基本的小应用程序对于像我这样的Rails新手来说是非常有益的。Rails应用程序的基础似乎隐藏了很长一段时间,Rack帮助我进一步揭开了帷幕

尽管如此,听从耶胡达的建议,查找西纳特拉是另一个惊喜。我现在有一个基本的sinatra应用程序在瘦实例中运行。它通过unix套接字与nginx通信,我认为这是标准的方式。Sinatra提供了一种非常优雅的方式来处理进入应用程序的不同请求和路由。您只需要一个
get'/'{}
就可以开始处理对虚拟主机的请求。为了添加更多内容(以干净的方式),我们只需在主文件中包含一个routes/script.rb

# cgi-bin.rb
# main file loaded as a sinatra app

require 'sinatra'

# load cgi routes
require 'routes/default'
require 'routes/contact'

# 404 behaviour
not_found do
  "Sorry, this CGI host does not recognize that request."
end
这些路由文件将调用存储在单独类库中的功能:

# routes/contact.rb
# contact controller

require 'lib/contact/contactTarget'
require 'lib/contact/contactPost'

post '/contact/:target/?' do |target|
  # the target for the message is taken from the URL
  msg = ContactPost.new(request, target)
  redirect msg.action, 302
end
弄明白这样一件简单的事情会让我有一段时间感到恐惧。我希望冷静地让nginx知道.rb文件将被执行,然后继续执行。现在,这个小sinatra应用程序已经启动并运行,如果我想在将来添加额外的功能,我将能够直接投入其中

实施:

ContactPost类处理消息传递方面。它只需要知道请求中的参数和电子邮件的目标。action启动所有操作并返回控制器重定向到的地址

有一个单独的ContactTarget类,它执行一些身份验证,以确保指定的目标接受来自request.referer中给定URL的消息。这是在ContactTarget::accept中处理的?正如我们可以从ContactPost::action方法中猜到的那样


# lib/contact/contactPost.rb

class ContactPost

# ...

  def action
    return failed unless @target.accept? @request.referer
    if send?
      successful
    else
      failed
    end
  end

# ...

end
ContactPost::successful和ContactPost::failed通过将HTML表单提供的路径与request.referer URI相结合来返回重定向地址。因此,所有行为都在HTML表单中指定。未来使用此脚本的网站只需在用户自己的~/cgi/contact.conf中列出,就可以离开了。这是因为ContactTarget在/home/:target/cgi/contact.conf中查找详细信息。也许有一天这会是不合适的,但就目前而言,这对我来说还不错

send方法非常简单,它创建一个简单电子邮件类的实例并将其发送出去。Email类基本上基于Ruby net/smtp文档中给出的标准用法示例

# lib/email/email.rb
require 'net/smtp'

class Email
  def initialize(from_alias, to, reply, subject, body)
    @from_alias = from_alias
    @from = "cgi_user@host.domain.com"
    @to = to
    @reply = reply
    @subject = subject
    @body = body
  end

  def send
    Net::SMTP.start('localhost', 25) do |smtp|
      smtp.send_message to_s, @from, @to
    end
  end

  def to_s
<<END_OF_MESSAGE
From: #{@from_alias} 
To: #{@to} 
Reply-To: #{@from_alias} 
Subject: #{@subject}
Date: #{DateTime::now().to_s}

#{@body}
END_OF_MESSAGE
  end
end
#lib/email/email.rb
需要“net/smtp”
班级电子邮件
def初始化(从_别名、收件人、回复、主题、正文)
@from_alias=from_alias
@from=“cgi_user@host.domain.com"
@to=to
@答复
@主语
@身体
结束
def发送
Net::SMTP.start('localhost',25)do | SMTP|
smtp.send_message to_s、@from、@to
结束
结束
def至美国

都在网络模块中,下面是一个示例:

  @net = Net::HTTP.new 'http://www.foo.com', 80
  @params = {:name => 'doris', :email => 'doris@foo.com'}

  # Create HTTP request
  req = Net::HTTP::Post.new( 'script.cgi', {} )
  req.set_form_data @params

  # Send request
  response = @net.start do |http|
    http.read_timeout = 5600
    http.request req
  end

都在网络模块中,下面是一个示例:

  @net = Net::HTTP.new 'http://www.foo.com', 80
  @params = {:name => 'doris', :email => 'doris@foo.com'}

  # Create HTTP request
  req = Net::HTTP::Post.new( 'script.cgi', {} )
  req.set_form_data @params

  # Send request
  response = @net.start do |http|
    http.read_timeout = 5600
    http.request req
  end

Ruby的CGI类可用于编写CGI脚本。请检查:


顺便说一下,不需要读取HTTP头。使用CGI类解析参数将很容易。然后,发送电子邮件并重定向。

Ruby的CGI类可用于编写CGI脚本。请检查:


顺便说一下,不需要读取HTTP头。使用CGI类解析参数将很容易。然后,发送电子邮件并重定向。

最好的方法可能是使用现有的Ruby库,如Sinatra:

require "rubygems"
require "sinatra"

get "/myurl" do
  # params hash available here
  # send email
end

您可能希望使用MailFactory来发送实际的电子邮件,但您肯定不需要费心处理标题或解析参数。

最好的方法可能是使用现有的Ruby库,如Sinatra:

require "rubygems"
require "sinatra"

get "/myurl" do
  # params hash available here
  # send email
end

您可能希望使用MailFactory来发送实际的电子邮件,但您肯定不需要费心处理标题或解析参数。

谢谢,看起来我需要Net模块来发送电子邮件,但我看不到使用它来读取发布的参数或发送标题的方法。我想也许我把事情复杂化了。我发现,您只需在cgi脚本中打印到标准输出,然后为重定向发送一个文本头。我将寻找一种类似的方法来读取url中给出的参数。一旦完成,我就离开了。谢谢,看起来我需要网络模块来发送电子邮件,但我看不到你的方法