You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求指导:不依赖库或Gem,用Ruby开发Gmail命令行客户端

纯Ruby实现Gmail命令行客户端核心思路

1. 手动实现OAuth2认证(无第三方Gem)

Gmail API要求OAuth2认证,基于Ruby标准库Net::HTTP和JSON即可完成流程:

  • 先在Google Cloud Console创建项目,启用Gmail API,生成桌面应用类型的OAuth2客户端ID和密钥。
  • 构造授权URL引导用户获取授权码:
    client_id = "你的客户端ID"
    redirect_uri = "urn:ietf:wg:oauth:2.0:oob" # 桌面应用专用回调
    scope = "https://www.googleapis.com/auth/gmail.readonly https://www.googleapis.com/auth/gmail.send"
    auth_url = "https://accounts.google.com/o/oauth2/v2/auth?client_id=#{client_id}&redirect_uri=#{redirect_uri}&scope=#{URI.encode_www_form_component(scope)}&response_type=code"
    puts "请访问以下URL授权:\n#{auth_url}"
    print "输入授权码:"
    code = gets.chomp
    
  • 用授权码交换access token和refresh token:
    token_uri = URI("https://oauth2.googleapis.com/token")
    params = {
      client_id: client_id,
      client_secret: "你的客户端密钥",
      code: code,
      redirect_uri: redirect_uri,
      grant_type: "authorization_code"
    }
    response = Net::HTTP.post_form(token_uri, params)
    token_data = JSON.parse(response.body)
    access_token = token_data["access_token"]
    refresh_token = token_data["refresh_token"]
    
  • 补充token刷新逻辑:当access token过期时,用refresh token请求新的access token。

2. 读取/接收邮件

通过Gmail REST API获取邮件列表与详情,解析MIME内容:

  • 获取最近N封邮件列表:
    def list_messages(access_token, max_results = 10)
      uri = URI("https://gmail.googleapis.com/gmail/v1/users/me/messages?maxResults=#{max_results}")
      req = Net::HTTP::Get.new(uri)
      req["Authorization"] = "Bearer #{access_token}"
      res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
      JSON.parse(res.body)["messages"] || []
    end
    
  • 解析单封邮件的主题、发件人、正文:
    def get_message(access_token, message_id)
      uri = URI("https://gmail.googleapis.com/gmail/v1/users/me/messages/#{message_id}?format=full")
      req = Net::HTTP::Get.new(uri)
      req["Authorization"] = "Bearer #{access_token}"
      res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
      msg_data = JSON.parse(res.body)
      
      # 提取并解码主题
      subject_header = msg_data["payload"]["headers"].find { |h| h["name"] == "Subject" }["value"]
      subject = subject_header.start_with?("=?UTF-8?B?") ? Base64.decode64(subject_header.split("?")[3]) : subject_header
      
      # 提取纯文本正文(简化处理,可扩展支持HTML)
      body = if msg_data["payload"]["body"]["size"] > 0
               Base64.urlsafe_decode64(msg_data["payload"]["body"]["data"])
             else
               plain_part = msg_data["payload"]["parts"].find { |p| p["mimeType"] == "text/plain" }
               Base64.urlsafe_decode64(plain_part["body"]["data"])
             end
      
      { subject: subject, body: body, from: msg_data["payload"]["headers"].find { |h| h["name"] == "From" }["value"] }
    end
    

3. 发送邮件

构造符合RFC 2822标准的邮件内容,通过API发送:

def send_email(access_token, to, subject, body)
  # 构造标准邮件格式
  email_content = <<~EMAIL
    From: 你的邮箱地址
    To: #{to}
    Subject: #{subject}
    Content-Type: text/plain; charset="UTF-8"

    #{body}
  EMAIL
  # 转换为API要求的base64url编码
  encoded_email = Base64.urlsafe_encode64(email_content).gsub("\n", "")
  
  uri = URI("https://gmail.googleapis.com/gmail/v1/users/me/messages/send")
  req = Net::HTTP::Post.new(uri)
  req["Authorization"] = "Bearer #{access_token}"
  req["Content-Type"] = "application/json"
  req.body = JSON.dump({ raw: encoded_email })
  
  res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
  res.is_a?(Net::HTTPSuccess)
end

4. 命令行交互逻辑

用ARGV解析用户输入的命令,实现基础交互:

# 先从本地文件读取已保存的token(需实现持久化逻辑)
access_token = "你的有效access token"

case ARGV[0]
when "list"
  messages = list_messages(access_token)
  messages.each_with_index do |msg, idx|
    puts "#{idx+1}. 邮件ID: #{msg['id']}"
  end
when "read"
  message_id = ARGV[1] || (puts "请指定邮件ID"; exit)
  msg = get_message(access_token, message_id)
  puts "发件人: #{msg[:from]}"
  puts "主题: #{msg[:subject]}"
  puts "正文:\n#{msg[:body]}"
when "send"
  to = ARGV[1] || (puts "请指定收件人"; exit)
  subject = ARGV[2] || (puts "请指定主题"; exit)
  body = ARGV[3..-1].join(" ") || (puts "请输入正文"; exit)
  send_email(access_token, to, subject, body) ? puts("邮件发送成功") : puts("邮件发送失败")
else
  puts "支持的命令:\n- list:列出最近10封邮件\n- read <邮件ID>:查看指定邮件\n- send <收件人> <主题> <正文>:发送邮件"
end

额外优化点

  • 把token信息持久化到本地文件(如~/.gmail_client_token.json),避免每次启动重新授权。
  • 增加API错误处理,比如token过期自动刷新、网络请求失败重试。
  • 扩展邮件解析逻辑,支持HTML正文、附件解析。

内容的提问来源于stack exchange,提问作者Saiyam-19

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 02:35:48