I need help with sending emails through Mailgun’s API in my Rails app. The problem is that I can’t get my email templates to work properly. I keep getting an error that says NoMethodError: undefined method 'each_byte' for nil:NilClass. Here’s what I’m trying to do:
class EmailService < ActionMailer::Base
def deliver_notification
request_data = Multimap.new
request_data[:from] = "Support Team <no-reply@#{@@domain_name}>"
request_data[:to] = "[email protected]"
request_data[:subject] = "Welcome Message"
request_data[:html] = File.read("#{Rails.root}/app/views/email_service/deliver_notification.html.erb")
## I also attempted this approach
request_data[:html] = render(template: "deliver_notification.html.erb")
result = RestClient.post "https://api:#{@@api_key}"\
"@api.mailgun.net/v3/#{@@domain_name}/messages", request_data
parsed_result = JSON.parse(result)
end
end
I know there are gems for this but I want to use the direct API because it gives me more control. Is there a way to render Rails view templates when using Mailgun’s HTTP API? Any alternative approach would be helpful too.
That nil error’s from File.read not finding the template. Try ActionView::Base.new instead - I got it working with ActionView::Base.new(ActionController::Base.view_paths).render(template: 'your_template', locals: {}). It processes ERB properly without ActionMailer or controller overhead. Just pass any variables your template needs through the locals hash.
The each_byte error happens because File.read can’t find your template - the path isn’t resolving right. Don’t inherit from ActionMailer::Base. Just make a standalone service class instead. I fixed this by using ApplicationController.new.render_to_string - it gives you Rails’ template rendering without the ActionMailer overhead. You can pass your template path, locals, and layout like this: ApplicationController.new.render_to_string(template: 'email_service/deliver_notification', locals: { user: @user }). This processes ERB correctly and you keep full Mailgun API control. Just remember to pass template variables through the locals hash since you won’t have ActionMailer’s instance variable magic. The controller method handles all the template compilation automatically.
Had the same problem when I bypassed ActionMailer for direct API calls. You’re reading the ERB template as plain text instead of actually processing it. I fixed this by creating a separate method to handle template rendering outside ActionMailer’s normal flow. You’ll need to manually process the ERB template and pass any instance variables it needs. I created a helper method using ERB.new to compile the template with proper binding context. This way I kept direct API control but could still use Rails templates. That each_byte error means File.read is returning nil - your template path is probably wrong. Check that the template actually exists there. Also set up any instance variables your template expects before rendering, since you’re skipping ActionMailer’s usual rendering pipeline.