Email body missing in Gmail when I add inline attachments - ruby

My UserMailer has an export method which sends an email to an address. This email has a CSV attachment and some inline PNG attachments. Here's the action which sends the email:
# user - the user to send the email to.
# csv_files - an array of hashes which represent CSV files to attach to the email.
# export_type - the name of the model being exported (either "customer" or "invoice").
#
# Examples
#
# UserMailer.export_email(current_user, files, "customer")
#
# Returns an email instance.
def export_email(user, csv_files, export_type)
#user = user
from_addy = %|'Exports' <exports#example.com>|
subject = "Your #{export_type} export files."
csv_files.each do |file|
# file[:content] will just be a big CSV string.
opts = { mime_type: 'text/plain', content: file[:content] }
attachments[file[:name]] = opts
end
# export_email_images is an array of hashes of image information defined elsewhere
# in the UserMailer class. These images are used in the email body.
# If I comment out this line and remove the images from my email body
# then everything works fine.
export_email_images.each { |opts| attachments.inline[opts[:name]] = opts }
# I have app/views/user_mailer/customer_export_email view files in both
# .html.erb and .text.erb formats.
mail(to: user.email, subject: subject, from: from_addy,
template_name: "#{export_type}_export_email")
end
However, when I send the email to Gmail in production, the body is missing:
Removing the inline attachments fixes the problem and the email body renders correctly (sans inline images obviously). What could be wrong here?

Related

How to attached image from post to email in Ruby

I am new to Ruby on Rails. I have a project using Ruby version 2.6.5. This project have a post with image using imagemagick. when i create a new post, currently i can send the post to my email, but without the post's images.
How to do to attached email with the image's post?
what i have done:-
class NotifierMailer < ApplicationMailer
default from: ENV['ADMIN_MAIL']
layout 'mailer'
def new_post(post)
#post = post
mail(to: #post.email,
bcc: ENV['ADMIN_MAIL'],
subject: " New Post.")
end
end
So, it is irrelevant if you use ImageMagick or not. The way to solve this is by
doing something like this:
def new_post(post, file_path)
#post = post
# You can add multiple attachments in a loop, just ensure the file names are uniq
attachments[File.basename(file_path)] = File.read(file_path)
mail(to: #post.email,
bcc: ENV['ADMIN_MAIL'],
subject: " New Post.")
end
The key here is that the file needs to be locally available, which it should be as this is a new post. If not you need to download the file to a temp file first, or you won't have a local file path to read from.

Error in 'get_tagged_response'

I've written a little Ruby script to manage my email (save into .txtfiles and remove spam). Here it goes:
require 'gmail'
username = 'gmail_username'
password = 'gmail_password'
gmail = Gmail.new(username, password)
# The piece below should save each unread email from website stated
# Into a .txt file on my machine
folder = '/home/alex/MAIL'
gmail.inbox.emails(:unread, from: 'website#work.ua').each do |email|
File.open(folder + email + '.txt', 'w+') { |f| f.write(email) }
end
# The piece below should remove spam letters
gmail.inbox.emails(:unread, from: 'site#eurolab.ua').each do |email|
email.delete!
end
gmail.logout
But when I try to run it via $ ruby managemail.rb it returns me the following error:
/home/alex/.rbenv/versions/2.3.0/lib/ruby/2.3.0/net/imap.rb:1198:in `get_tagged_response': Unknown command m1mb83666172lbl (Net::IMAP::BadResponseError)
What have I done wrong?

How do I call a function in Ruby?

I'm trying to call but I keep getting an error. This is my code:
require 'rubygems'
require 'net/http'
require 'uri'
require 'json'
class AlchemyAPI
#Setup the endpoints
##ENDPOINTS = {}
##ENDPOINTS['taxonomy'] = {}
##ENDPOINTS['taxonomy']['url'] = '/url/URLGetRankedTaxonomy'
##ENDPOINTS['taxonomy']['text'] = '/text/TextGetRankedTaxonomy'
##ENDPOINTS['taxonomy']['html'] = '/html/HTMLGetRankedTaxonomy'
##BASE_URL = 'http://access.alchemyapi.com/calls'
def initialize()
begin
key = File.read('C:\Users\KVadher\Desktop\api_key.txt')
key.strip!
if key.empty?
#The key file should't be blank
puts 'The api_key.txt file appears to be blank, please copy/paste your API key in the file: api_key.txt'
puts 'If you do not have an API Key from AlchemyAPI please register for one at: http://www.alchemyapi.com/api/register.html'
Process.exit(1)
end
if key.length != 40
#Keys should be exactly 40 characters long
puts 'It appears that the key in api_key.txt is invalid. Please make sure the file only includes the API key, and it is the correct one.'
Process.exit(1)
end
#apiKey = key
rescue => err
#The file doesn't exist, so show the message and create the file.
puts 'API Key not found! Please copy/paste your API key into the file: api_key.txt'
puts 'If you do not have an API Key from AlchemyAPI please register for one at: http://www.alchemyapi.com/api/register.html'
#create a blank file to hold the key
File.open("api_key.txt", "w") {}
Process.exit(1)
end
end
# Categorizes the text for a URL, text or HTML.
# For an overview, please refer to: http://www.alchemyapi.com/products/features/text-categorization/
# For the docs, please refer to: http://www.alchemyapi.com/api/taxonomy/
#
# INPUT:
# flavor -> which version of the call, i.e. url, text or html.
# data -> the data to analyze, either the the url, text or html code.
# options -> various parameters that can be used to adjust how the API works, see below for more info on the available options.
#
# Available Options:
# showSourceText -> 0: disabled (default), 1: enabled.
#
# OUTPUT:
# The response, already converted from JSON to a Ruby object.
#
def taxonomy(flavor, data, options = {})
unless ##ENDPOINTS['taxonomy'].key?(flavor)
return { 'status'=>'ERROR', 'statusInfo'=>'Taxonomy info for ' + flavor + ' not available' }
end
#Add the URL encoded data to the options and analyze
options[flavor] = data
return analyze(##ENDPOINTS['taxonomy'][flavor], options)
print
end
**taxonomy(text,"trees",1)**
end
In ** ** I have entered my call. Am I doing something incorrect. The error I receive is:
C:/Users/KVadher/Desktop/testrub:139:in `<class:AlchemyAPI>': undefined local variable or method `text' for AlchemyAPI:Class (NameError)
from C:/Users/KVadher/Desktop/testrub:6:in `<main>'
I feel as though I'm calling as normal and that there is something wrong with the api code itself? Although I may be wrong.
Yes, as jon snow says, the function (method) call must be outside of the class. The methods are defined along with the class.
Also, Options should be a Hash, not a number, as you call options[flavor] = data, which is going to cause you another problem.
I believe maybe you meant to put text in quotes, as that is one of your flavors.
Furthermore, because you declared a class, this is called an instance method, and you must make an instance of the class to use this:
my_instance = AlchemyAPI.new
my_taxonomy = my_instance.taxonomy("text", "trees")
That's enough to get it to work, it seems like you have a ways to go to get this all working though. Good luck!

How to pass variables into Mail body template?

I am trying to write simple mailer in Sinatra which sends email with params variables.
require 'sinatra'
require 'mail'
class App < Sinatra::Base
post '/test_mailer' do
company = params['Field6']
email = params['Field5']
puts "Company name: #{company}"
puts "Email: #{email}"
mail = Mail.new do
from 'me#mydomain.com'
to 'me#mydomain.com'
subject 'Here is the image you wanted'
text_part do
body "Company Name \n === \n #{company} \n \n Email \n === \n #{email}"
end
end
mail.deliver!
end
end
How to move email template to test_mailer.txt with company and email variables ?
I'm not sure I understand you - you want an separate email template file, right? I'm thinking you could use an erb, or haml template and then do something like the following:
text_part do
body erb(:test_mailer)
end
Your test_mailer.erb file would then contain your email template.
Here shows how something similar is done using pony.

Jekyll - generating JSON files alongside the HTML files

I'd like to make Jekyll create an HTML file and a JSON file for each page and post. This is to offer a JSON API of my Jekyll blog - e.g. a post can be accessed either at /posts/2012/01/01/my-post.html or /posts/2012/01/01/my-post.json
Does anyone know if there's a Jekyll plugin, or how I would begin to write such a plugin, to generate two sets of files side-by-side?
I was looking for something like this too, so I learned a bit of ruby and made a script that generates JSON representations of Jekyll blog posts. I’m still working on it, but most of it is there.
I put this together with Gruntjs, Sass, Backbonejs, Requirejs and Coffeescript. If you like, you can take a look at my jekyll-backbone project on Github.
# encoding: utf-8
#
# Title:
# ======
# Jekyll to JSON Generator
#
# Description:
# ============
# A plugin for generating JSON representations of your
# site content for easy use with JS MVC frameworks like Backbone.
#
# Author:
# ======
# Jezen Thomas
# jezenthomas#gmail.com
# http://jezenthomas.com
module Jekyll
require 'json'
class JSONGenerator < Generator
safe true
priority :low
def generate(site)
# Converter for .md > .html
converter = site.getConverterImpl(Jekyll::Converters::Markdown)
# Iterate over all posts
site.posts.each do |post|
# Encode the HTML to JSON
hash = { "content" => converter.convert(post.content)}
title = post.title.downcase.tr(' ', '-').delete("’!")
# Start building the path
path = "_site/dist/"
# Add categories to path if they exist
if (post.data['categories'].class == String)
path << post.data['categories'].tr(' ', '/')
elsif (post.data['categories'].class == Array)
path << post.data['categories'].join('/')
end
# Add the sanitized post title to complete the path
path << "/#{title}"
# Create the directories from the path
FileUtils.mkpath(path) unless File.exists?(path)
# Create the JSON file and inject the data
f = File.new("#{path}/raw.json", "w+")
f.puts JSON.generate(hash)
end
end
end
end
There are two ways you can accomplish this, depending on your needs. If you want to use a layout to accomplish the task, then you want to use a Generator. You would loop through each page of your site and generate a new .json version of the page. You could optionally make which pages get generated conditional upon the site.config or the presence of a variable in the YAML front matter of the pages. Jekyll uses a generator to handle slicing blog posts up into indices with a given number of posts per page.
The second way is to use a Converter (same link, scroll down). The converter will allow you to execute arbitrary code on your content to translate it to a different format. For an example of how this works, check out the markdown converter that comes with Jekyll.
I think this is a cool idea!
Take a look at JekyllBot and the following code.
require 'json'
module Jekyll
class JSONPostGenerator < Generator
safe true
def generate(site)
site.posts.each do |post|
render_json(post,site)
end
site.pages.each do |page|
render_json(page,site)
end
end
def render_json(post, site)
#add `json: false` to YAML to prevent JSONification
if post.data.has_key? "json" and !post.data["json"]
return
end
path = post.destination( site.source )
#only act on post/pages index in /index.html
return if /\/index\.html$/.match(path).nil?
#change file path
path['/index.html'] = '.json'
#render post using no template(s)
post.render( {}, site.site_payload)
#prepare output for JSON
post.data["related_posts"] = related_posts(post,site)
output = post.to_liquid
output["next"] = output["next"].id unless output["next"].nil?
output["previous"] = output["previous"].id unless output["previous"].nil?
#write
#todo, figure out how to overwrite post.destination
#so we can just use post.write
FileUtils.mkdir_p(File.dirname(path))
File.open(path, 'w') do |f|
f.write(output.to_json)
end
end
def related_posts(post, site)
related = []
return related unless post.instance_of?(Post)
post.related_posts(site.posts).each do |post|
related.push :url => post.url, :id => post.id, :title => post.to_liquid["title"]
end
related
end
end
end
Both should do exactly what you want.

Resources