Goal: Use unique email address in email header To: field (see message_class) of MIME Html Message.
File: database.rb Here I connect to the database and I loop through the rows in table rcpt
. Then I store the value in row["email"]
.
require 'mysql2'
class Db
def con
@db_host = "localhost"
@db_user = "root"
@db_pass = "password"
@db_name = "table_db"
client = Mysql2::Client.new(:host => @db_host, :unsername => @db_user, :password => @db_pass, :database => @db_name)
rcpt = client.query("SELECT * from rcpt")
rcpt.each do |row|
row["email"]
end
end
end
Ouput of con
method without ["email"]:
{"id"=>01, "email"=>"example1@example.com"}
{"id"=>02, "email"=>"example2@example.com"}
Output of con
method with ["email"]:
example1@example.com
example2@example.com
DB Schema:
mysql> describe rcpt;
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| email | varchar(150) | NO | UNI | NULL | |
+-------+--------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
File: message_class.rb Here I create the method pull_rcpt
which then stores row["email"]
. Then I'm trying to use the pull_rcpt
method in message
heredoc. Now comes my problem: in the To:
field, I'm trying to pass the users email address I'm currently sending to, so it should change with the receiving email address. It still uses the email address of the first contact in the array/Db. What am I doing wrong?
require 'dkim'
require './database'
class Email
def pull_rcpt
rcpt = Db.new
rcpt.con
end
def data
Dkim::domain = 'example.com'
Dkim::selector = 'mail'
Dkim::private_key = open('/path/to/keys/example.com/mail.private').read
message = <<~MESSAGE
From: Eva <test@example.com>
To: Dani <#{pull_rcpt[0]["email"]}>
MIME-Version: 1.0
Content-Type: text/html
Content-Transfer-Encoding: 8bit
Subject: Test Subject
This is an email message.
<h1>Test</h1>
MESSAGE
end
end
File: mailer_class.rb In my mailer_class I have two method's rcpt_to
and message
. Rcpt_to contains an array contacts
, which holds the values of row["email"]
. Message builds the email.
require './database'
require './message_class'
def rcpt_to
#conn zu DB & take rcpt
contacts = []
contacts = Db.new
contacts.con
end
def message
#message
message = Email.new
end
A few lines later inside a for loop
I use the methods as follows:
for rcpt in rcpt_to do
@protocol = { ehlo: "ehlo", mail_from: "eva@example.com", rcpt_to: [rcpt["email"]], data: Dkim.sign(message.data) }
end
Here is the header of example2@example.com which is the second record in the database:
From: Eva <test@example.com>
To: Dani <example1@example.com> <--- This should be example2(value in hash of second entry in database) not example1
MIME-Version: 1.0
Content-Type: text/html
Content-Transfer-Encoding: 8bit
Subject: Test Subject
Content-Length: 40
So the only thing not working is the dynamic To: field in the email header. The rest is just working fine and all records in the database receive an email.
As already mentioned, this line is the core of the problem: <#{pull_rcpt[0]["email"]}>
. You are explicitly selecting the first element in the database. To create the header dynamically, you will have to pass an argument to the data-method.
So here's one way to solve this:
In class Email, change def data
to def data(dynamic_email)
, and
To: Dani <#{pull_rcpt[0]["email"]}>
to To: Dani <#{dynamic_email}>
and within the loop:
data: Dkim.sign(message.data)
=> data: Dkim.sign(message.data(rcpt["email"]))
Something like that should work.
As a side note, your code could do some refactoring. For example, the con-method you have written doesn't work the way you think. "each" returns the array itself. If you put it on the last line of a method like that, it doesn't serve any purpose. In this case, it would be equivalent to writing return rcpt
. If you want the method to return an array of email addresses, you should use map instead of each (or even better, rewrite your sql query). But of course, if you change that, it'll break the rest of your code. The lazy solution is just to remove the each-loop...