2026-07-15

Send email from rails console

Stefan Bogdanescu

Stefan Bogdanescu

Founder & Senior Architect

Send email from rails console

Sending Emails from the Rails Console: Troubleshooting Delivery Issues

As a senior developer, I frequently encounter situations where code behaves differently in a web request context versus a direct command-line environment, especially when dealing with external services like email delivery. The issue you are facing—where sending emails works fine in a controller but fails in the Rails console—is a common stumbling block related to environment setup and how background processes handle external communication protocols.

Let's dive into why this happens and how we can fix it, focusing on robust practices that align with modern application development, much like the principles advocated by Laravel.

The Console vs. Controller Discrepancy

When you execute code within a Rails controller, the request lifecycle provides a rich environment. Frameworks like Action Mailer are tightly integrated into Rack/Rails middleware, which manages configuration loading, environment variables, and session data necessary for external services.

However, when you invoke commands directly in the rails console, you are running a standalone Ruby process. While your application code (the mailer logic) runs fine, the underlying system calls required to connect to an external Mail Transfer Agent (MTA) like Sendmail might fail due to missing context or environment variables that the web server implicitly provides.

The output you see—receiving a TMail::StringPort object back—indicates that the preparation of the mail object succeeded, but the actual transmission step, which relies on the operating system's ability to connect via the configured ports (port and bodyport), is where the failure occurs in the console environment.

Diagnosing the Sendmail Failure

Since you are on an Ubuntu server using Sendmail, the problem usually boils down to one of three areas when running from the console:

  1. Environment Variables: The console session might not inherit all necessary environment variables (like MAILER_HOST, port settings, or user permissions) that the web server environment automatically loads.
  2. MTA Path/Permissions: Direct execution via the console might bypass the standard system path configuration that the web application relies on for SMTP communication.
  3. Configuration Specificity: The way you are passing host and port information directly to the Mailer method might be conflicting with the underlying system's default settings when executed outside of a full request cycle.

The Solution: Ensuring Context and Explicit Configuration

The best practice is to ensure that any external dependency—especially one involving network communication like email—is configured explicitly, regardless of where the code is executed. Instead of relying solely on implicit environment settings, we need to ensure the mailer knows exactly how to connect.

Recommended Approach: Use Environment Variables and Explicit Setup

For production systems, configuration should primarily reside in environment files (e.g., .env) rather than being hardcoded or passed ad-hoc via console calls. When dealing with services like email, it is crucial that these settings are consistently loaded.

If you must run this from the console for testing, explicitly set the necessary configuration before invoking the mailer. This mimics the full environment setup:

# 1. Ensure your environment variables are set (e.g., in .env or shell)
# For testing purposes, ensure these are correct for your Sendmail setup.

# 2. Explicitly configure connection details if needed for testing outside a request scope
# Note: This often requires configuring the transport layer directly if using a custom setup.
# For standard Rails setups relying on system mail tools, verifying the OS configuration is key.

user = User.find(1)
host = "mydomainname.example"
port = 587 # Standard SMTP port

begin
  # Attempt to deliver the mail using explicit parameters
  mailer_result = Mailer.deliver_signup(user, host, "password")
  puts "Mail delivery attempt successful (Object received): #{mailer_result.class}"

rescue => e
  puts "Error during email delivery: #{e.message}"
end

Best Practice: Testing Delivery Outside the Rails Framework

If you are strictly testing connectivity to an external MTA like Sendmail, running direct system commands often provides a more reliable test than relying solely on the framework's abstraction layer when debugging infrastructure issues. Ensure that your shell environment can successfully execute basic mail tests independently of the Ruby process.

For complex integrations involving sending emails, always remember to focus on robust configuration management, which is central to building scalable applications, as seen in projects utilizing modern patterns from Laravel.

Conclusion

The behavior you observed—successful delivery in the controller but failure in the console—points away from a bug in your Mailer logic itself and squarely toward an environmental or context issue during execution. By ensuring that all necessary host, port, and system permissions are correctly established, either through explicit configuration checks or by confirming the underlying OS setup (like Sendmail configuration), you can resolve these discrepancies. Always treat the console as a separate execution environment; ensure it has the full context required for external communication to succeed.

Note: Blog content is currently available in English.

Tags:

Enhance your marketing setup with your own email marketing platform.

Join the growing number of SaaS platforms using Laravel Mail to offer email marketing solutions to their customers.