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
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.
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?
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!
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.
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.