How can I change the name attribute to "email" in the user login form? Users do not always login with their Drupal user name but in some projects by email for example.

What would be the Drupalitically correct way in this case to change the "name"-Attribute of the user name login text field in the user login form? For example to change it to "email" so that a HubSpot JS Snippet would recognize login form submissions? How would this be done in both Drupal 7 and Drupal 8?
This is a variation of a frequently asked question.

The user login form for Drupal is built using Drupal Form API.

In Drupal 7 core, the user login form is declared in user.module:

https://github.com/drupal/drupal/blob/7.x/modules/user/user.module#L2111

  // Display login form:
  $form['name'] = array('#type' =&gt; 'textfield',
    '#title' =&gt; t('Username'),
    '#size' =&gt; 60,
    '#maxlength' =&gt; USERNAME_MAX_LENGTH,
    '#required' =&gt; TRUE,
  );

  $form['name']['#description'] = t('Enter your @s username.', array('@s' =&gt; variable_get('site_name', 'Drupal')));
  $form['pass'] = array('#type' =&gt; 'password',
    '#title' =&gt; t('Password'),
    '#description' =&gt; t('Enter the password that accompanies your username.'),
    '#required' =&gt; TRUE,
  );
  $form['#validate'] = user_login_default_validators();
  $form['actions'] = array('#type' =&gt; 'actions');
  $form['actions']['submit'] = array('#type' =&gt; 'submit', '#value' =&gt; t('Log in'));


And in Drupal 8 core, it's declared in UserLoginForm.php:

https://github.com/drupal/core/blob/8.8.x/modules/user/src/Form/UserLoginForm.php#L94

    // Display login form:
    $form['name'] = [
      '#type' =&gt; 'textfield',
      '#title' =&gt; $this-&gt;t('Username'),
      '#size' =&gt; 60,
      '#maxlength' =&gt; UserInterface::USERNAME_MAX_LENGTH,
      '#description' =&gt; $this-&gt;t('Enter your @s username.', ['@s' =&gt; $config-&gt;get('name')]),
      '#required' =&gt; TRUE,
      '#attributes' =&gt; [
        'autocorrect' =&gt; 'none',
        'autocapitalize' =&gt; 'none',
        'spellcheck' =&gt; 'false',
        'autofocus' =&gt; 'autofocus',
      ],
    ];

    $form['pass'] = [
      '#type' =&gt; 'password',
      '#title' =&gt; $this-&gt;t('Password'),
      '#size' =&gt; 60,
      '#description' =&gt; $this-&gt;t('Enter the password that accompanies your username.'),
      '#required' =&gt; TRUE,
    ];

    $form['actions'] = ['#type' =&gt; 'actions'];
    $form['actions']['submit'] = ['#type' =&gt; 'submit', '#value' =&gt; $this-&gt;t('Log in')];


If you need to customize it, you should not edit the code in core. Instead, you should do it using hook_form_alter() in a custom module.

This is a classic example of one of the first exercises new developers can do to learn how to build Drupal modules, and a web search should reveal many tutorials.

As @Jaypan pointed out in the comments above, you probably want to change the label on the field ($form['name']['#title']) rather than its name.

Here's an example of how to do that with hook_form_alter() in Drupal 7:

function YOUR_MODULE_NAME_form_alter(&amp;$form, &amp;$form_state, $form_id) {
  if ($form_id=='user_login') {

     // This will change the field label from "Username" to "Email".
     // The t() function marks the string as translatable by Drupal.
     $form['name']['#title'] = t("Email");

  }
}


In Drupal 8, it's almost the same, but $form_state is now an object and must be type hinted as an instance of \Drupal\Core\Form\FormStateInterface:

function YOUR_MODULE_NAME_form_alter(&amp;$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  if ($form_id=='user_login') {

     // This will change the field label from "Username" to "Email".
     // The t() function marks the string as translatable by Drupal.
     $form['name']['#title'] = t("Email");

  }
}