Overview
--------
Allows filefield downloads to be restricted until the requester confirms the email address. This email address is stored in the database and reported back to privileged users. The requester receives a mail with a link to the requested file.

Features
--------
Captures file downloads of files which are provided through a filefield and configured as tracked. Anonymous users are redirected to a form where they can enter their email address, instead of immediately starting the download (which would be standard behavior). After submitting the email address, they receive an email witch contains the download link as well as configurable subject and text areas.

For logged in users the download starts immediately as usual.

Download statistics of tracked files by anonymous and logged in users are provided under Reports / Tracked downloads.

Requirements
------------
The File module (from Core) must be enabled.
A content type must contain a filefield.
A configured mail server

Configuration
-------------
Install as usual. Click the "manage display" tab of the content type which contains the filefield which you want to be tracked. Set the format of the filefield to "Generic file (with tracking)". Save the display settings.

Go to configuration / content authoring / Filefield Mail Configuration. Insert the subject of the mail, the text of the body field before (e.g. Thank you for your interest..) and behind (e.g. Sincerely, Your Fubar Team) the download link. Save the configuration.

Make sure that Public file system path under Configuration / File Systems is set correctly.

Recommended Modules
-------------------
It is strongly recommended to use Captcha or a module with similar functionality. FileField Mail sends a email to an address provided by an anonymous user. Therefore it can be misused by malicious software to fill someones mailbox. Prevent this by using a module which ensures that the user is human.

Similar Projects
----------------
See http://drupal.org/node/1613392 for a comparison of download tracking modules.

Filefield track and Webform Protected Downloads are similar modules, because they have D7 versions and collect an e-mail address from the
user.

Filefield track captures the download and redirects the user to a form. The user can enter an email address. Filefield track does not send an email, but starts the download immediately after submission. Thus, the email address is not verified and any formally correct address will be accepted.

Webform Protected Downloads tracks file downloads only from webforms. It does not track downloads from content types. It replaces the download link in a webform with a field to insert the email address. The replacement of the link makes the page less readable for the user, especially if the page contains a whole list of links. Webform Protected Downloads sends an email to the address to verify it. The text of the mail with the download link can not be configured.

Filefield Mail combines features of both modules and extends them. It tracks filefields in content types. The links are not replaced, so that they still lock the way they were configured. The mail address is
verified by sending an email. The text of the email can be configured.

Some of the code is taken from those two modules. Thank you guys :-)

Why a new module?
-----------------
The functionalities of Webform Protected Downloads and FileField Mail can not be merged, since one focuses exclusively on webforms and the other on all kind of content types. It might have been possible to write a patch for Fielfield Track. This would have been a very extensive patch. But there are clear reasons against that.

FileField Track has some functionality, which does not make sense for FileField Mail, e.g. the "URL to file (with tracking)" format and setting cookies. It would not be appropriate to remove this functionality in a patch.

The FileField Track module uses cookies to relieve the unregistered user from having to type the e-mail address repeatedly for every download. This may be useful if the download starts immediately after insertion of the address and the visitors computer is used only by one person.

But it prevents the visitor from having different downloads sent to different email accounts. And it becomes a problem, if more than one visitors share the same computer without different user accounts. Therefore, FileField Mail omits using cookies.

This different necessities are mutually exclusive and can not sensibly be built into the same module.

http://drupal.org/node/894256 says: "Module duplication (lower priority) makes it hard to find the right module". This problem is addressed for the download tracker modules through http://drupal.org/node/1613392, where the differences are clearly visible.

FileField Mail has been running for several month on the productive site of a large company in the chemical industry. As I have heard no complaints about it, it seems fairly stable.

FileField Mail is for D7

Link to my project page:
http://drupal.org/sandbox/MartinMayer/1877466

Link to my git repository:
http://git.drupal.org/sandbox/MartinMayer/1877466.git 7.x-1.x

Reviews of other projects:
http://drupal.org/node/1100840#comment-6389798
http://drupal.org/node/1711898#comment-6996386 and http://drupal.org/node/1711898#comment-6999656 (they concern the same review)
http://drupal.org/node/1846194#comment-7001388

Comments

Martin Mayer’s picture

Status: Needs review » Needs work

just found an error.

Martin Mayer’s picture

Status: Needs work » Needs review

error already fixed

monymirza’s picture

Status: Needs review » Needs work

filefield_mail.info
-dependencies[] = file- added twice

filefield_mail.admin.inc
for type textarea attribs;
remove '#size' => 80,
enter #cols + #rows

Martin Mayer’s picture

Status: Needs work » Needs review

Thank's monymirza!
I fixed the issues from #3

jnicola’s picture

Status: Needs review » Needs work

Par review shows no errors, good stuffs!

http://ventral.org/pareview/httpgitdrupalorgsandboxmartinmayer1877466git

Manual Review:

Hmmm, I wonder about this code in fielfield_mail.com

  if (empty($record)) {
    $record = array(
      'fid' => $fid,
      'email' => $email,
      'changed' => time(),
    );
    drupal_write_record('filefield_mail', $record);
  }

Is it me... or are you taking direct user input ($email being $email = $form_state['values']['email'];) and inserting it directly into the database via drupal_write_record() ...

I tried to google if Drupal write record automatically sanitizes it's input, but couldn't find anything on it. Maybe just double check or consider it? Maybe you can sanitize it with t()? Anyways, just a thought.

No further thoughts or issues spotted by me (but I'm a noob!)

How it actually worked when installed:

Directions were fine. Went ahead and installed, configured, setup content type, uploaded image. Downloaded logged in fine (skipped straight to download). Logged out and went to download as an anonymous user. Two things:

1: I got an email, but the link provided was bunk: http://dev.jessenicola.com/module-testing//Jellyfish.jpg , Should be sites/default/files/Jellyfish.jpg

2: Should you maybe check anonymous download email addresses against user emails and perhaps just tell them to login to download the file?

Anyways, it didn't work as promised despite nothing blatantly obvious being wrong in the code. Marking as "needs work"

Martin Mayer’s picture

Thank you jnicola!

The user input has been sanitized through

function filefield_mail_download_form_validate($form, &$form_state) {
  if (!valid_email_address($form_state['values']['email'])) {
    form_set_error('download', t('Please enter a valid email address.'));
  }
}

The valid_email_address function rejects any input which is not a valid email address. To make doubly sure that nothing can happen, I added

 $email = filter_xss($form_state['values']['email'],$allowed_tags = array());

Thank you for pointing out the issue with the broken link. I found out that this can occur when the public file system path is not set in the file system configuration (downloading private files by unregistered users makes no sense). I changed the way the download path is constructed and use the file_create_url() function now. I also extended the configuration instructions.

Checking if the provided email address belongs to a registered user is rather a matter of use case. I assume that a registered user knows what s/he does and maybe wants to send a link to the email account, rather than downloading directly. A reason could be to download the file later on another computer.

Martin Mayer’s picture

Issue summary: View changes

Typo corrected

Martin Mayer’s picture

Status: Needs work » Needs review
alexmoreno’s picture

Hi Martin,

very nice job, thank you very much for your job and contribution to the community.

Just a couple of comments.

The code itself is quite nice, well written and it is easily readable. I just would improve it adding a couple of comments following the Doxygen and comment formatting conventions http://drupal.org/node/1354

Executing paraview tool i also get this issues:

filefield_mail.inc

Line 66: missing space after comma [style_comma_spacing]
  $email = filter_xss($form_state['values']['email'],$allowed_tags = array());
Line 66: No space found after comma in function call [sniffer_generic_functions_functioncallargumentspacing_nospaceaftercomma]
  $email = filter_xss($form_state['values']['email'],$allowed_tags = array());
Line 83: The $string argument to t() should not begin or end with a space. (Drupal Docs) [i18n_11]
  drupal_set_message(t('Thank you! You will shortly receive an e-mail with your personal download link. '), 'status', TRUE);
Line 93: Use ANSI standard <> instead of != [sql_noteq]
  $result = db_query('SELECT * FROM {filefield_mail} WHERE ((uid = 0 AND email = :email) OR (uid != 0 AND uid = :uid)) AND fid = :fid', array(

Thank you very much again.

Martin Mayer’s picture

Issue summary: View changes

Configuration instructions refined.

Martin Mayer’s picture

Issue summary: View changes

Added a review

Martin Mayer’s picture

Hi urwen,

thanks a lot for the positive feedback :-)

I added comments to make the module more understandable. I try to explain everything necessary without being verbose. I hope I found the right balance now.

I also resolved the issues from the pareview tool and checked again. See http://ventral.org/pareview/httpgitdrupalorgsandboxmartinmayer1877466git...

To prevent the admin from including malicious HTML in the mail content I added filter_xss functions. Now the mail can contain only harmless HTML content.

If you find no further issues, I would be happy about a "reviewed & tested by the community" status.
I will do some reviews of other modules myself as soon as possible, to participate in the review bonus program.

Martin Mayer’s picture

Issue summary: View changes

review added

alexmoreno’s picture

Status: Needs review » Reviewed & tested by the community

No problem Martin, thank you very much for your effort.

In what it concerns myself, I am happy about the review and tested status :-). Let me know if it is everything ok, it is my first time :-)

Martin Mayer’s picture

Issue tags: +PAReview: review bonus

PAReview: review bonus

Martin Mayer’s picture

Thank you urwen! I will come back to you.

a_thakur’s picture

I cloned the repository, the directory name is filefield_mai, a small typo "l" is missing. It should be filefield_mail

jnicola’s picture

Just pulled the module again and test. It works for me :)

Martin Mayer’s picture

Hi a_thakur, thank you for checking out the module. I cannot find the typo. Can you point out more details? If I check it out, the name seems ok.

klausi’s picture

Status: Reviewed & tested by the community » Fixed

manual review:

  1. filefield_mail_stats(): why do you need the foreach loop? Can't you use ->fetchAll() or similar methods on the result? Please add a comment.
  2. theme_filefield_mail_link(): no need to use check_plain() here, the l() function will sanitize attributes for you. And double escaping is bad.
  3. filefield_mail_download_form_submit(): why do you call filter_xss() here? The email can never be anything malicious, since you checked that already in the validation function? Also the email is never printed to the user in this function? "When handling data, the golden rule is to store exactly what the user typed. When a user edits a post they created earlier, the form should contain the same things as it did when they first submitted it. This means that conversions are performed when content is output, not when saved to the database" http://drupal.org/node/28984
  4. "filter_xss($mail_subject, $allowed_tags = array());": just pass array() here? Why the $allowed_tags variable?
  5. filefield_mail_send_mail(): You should not pass the finished message to drupal_mail(), only the necessary variables. Markup and layout should all be done in filefield_mail_mail(). Make sure to read the documentation of drupal_mail() again.
  6. "'Pragma' => 'hack',": what is that needed for? Please add a comment.
  7. filefield_mail_send_mail(): IMO there is no need to run sanitization functions like filter_xss() on emails. I started a discussion to finally clarify this: http://groups.drupal.org/node/280368

Although you should definitively fix those issues, they are not critical application blockers, so ...

Thanks for your contribution, Martin Mayer!

I updated your account to let you promote this to a full project and also create new projects as either a sandbox or a "full" project.

Here are some recommended readings to help with excellent maintainership:

You can find lots more contributors chatting on IRC in #drupal-contribute. So, come hang out and get involved!

Thanks, also, for your patience with the review process. Anyone is welcome to participate in the review process. Please consider reviewing other projects that are pending review. I encourage you to learn more about that process and join the group of reviewers.

Thanks to the dedicated reviewer(s) as well.

Martin Mayer’s picture

Thank you klausi and all the reviewers! I really appreciate your time and effort! Special thanks to klausi for your thorough expert review and valuable tips.

alexmoreno’s picture

good job Martin :-)

Automatically closed -- issue fixed for 2 weeks with no activity.

Anonymous’s picture

Issue summary: View changes

review added