[ Index ]
 

Code source de Mantis 1.1.0rc3

Accédez au Source d'autres logiciels libres

Classes | Fonctions | Variables | Constantes | Tables

title

Body

[fermer]

/core/ -> email_api.php (source)

   1  <?php
   2  # Mantis - a php based bugtracking system
   3  
   4  # Copyright (C) 2000 - 2002  Kenzaburo Ito - kenito@300baud.org
   5  # Copyright (C) 2002 - 2007  Mantis Team   - mantisbt-dev@lists.sourceforge.net
   6  
   7  # Mantis is free software: you can redistribute it and/or modify
   8  # it under the terms of the GNU General Public License as published by
   9  # the Free Software Foundation, either version 2 of the License, or
  10  # (at your option) any later version.
  11  #
  12  # Mantis is distributed in the hope that it will be useful,
  13  # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15  # GNU General Public License for more details.
  16  #
  17  # You should have received a copy of the GNU General Public License
  18  # along with Mantis.  If not, see <http://www.gnu.org/licenses/>.
  19  
  20      # --------------------------------------------------------
  21      # $Id: email_api.php,v 1.139.2.3 2007-10-22 07:40:59 vboctor Exp $
  22      # --------------------------------------------------------
  23  
  24      $t_core_dir = dirname( __FILE__ ).DIRECTORY_SEPARATOR;
  25  
  26      define( 'PHPMAILER_PATH', $t_core_dir . 'phpmailer' . DIRECTORY_SEPARATOR );
  27      
  28      require_once ( $t_core_dir . 'current_user_api.php' );
  29      require_once ( $t_core_dir . 'bug_api.php' );
  30      require_once ( $t_core_dir . 'custom_field_api.php' );
  31      require_once ( $t_core_dir . 'string_api.php' );
  32      require_once ( $t_core_dir . 'history_api.php' );
  33      require_once ( $t_core_dir . 'email_queue_api.php' );
  34      require_once ( $t_core_dir . 'relationship_api.php' );
  35      require_once ( 'disposable' . DIRECTORY_SEPARATOR . 'disposable.php' );
  36      require_once( PHPMAILER_PATH . 'class.phpmailer.php' );
  37  
  38      # reusable object of class SMTP
  39      $g_phpMailer_smtp = null;
  40  
  41      ###########################################################################
  42      # Email API
  43      ###########################################################################
  44  
  45      # Use a simple perl regex for valid email addresses.  This is not a complete regex,
  46      # as it does not cover quoted addresses or domain literals, but it is simple and
  47      # covers the vast majority of all email addresses without being overly complex.
  48      # Callers must surround this with appropriate delimiters with case insentive options.
  49  	function email_regex_simple() {
  50          return "(([a-z0-9!#*+\/=?^_{|}~-]+(?:\.[a-z0-9!#*+\/=?^_{|}~-]+)*)" .                 # recipient
  51              "\@((?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?))";    # @domain
  52      }
  53  
  54      # --------------------
  55      # Return a perl compatible regular expression that will
  56      #  match a valid email address as per RFC 822 (approximately)
  57      #
  58      # The regex will provide too matched groups: the first will be the
  59      #  local part (or mailbox name) and the second will be the domain
  60  	function email_get_rfc822_regex() {
  61          # Build up basic RFC 822 BNF definitions.
  62  
  63          # list of the special characters: ( ) < > @ , ; : \ " . [ ]
  64          $t_specials = '\(\)\<\>\@\,\;\:\\\"\.\[\]';
  65          # the space character
  66          $t_space    = '\040';
  67          # valid characters in a quoted string
  68          $t_char     = '\000-\177';
  69          # control characters
  70          $t_ctl      = '\000-\037\177';
  71  
  72          # a chunk of quoted text (anything except " \ \r are valid)
  73          $t_qtext_re = '[^"\\\r]+';
  74          # match any valid character preceded by a backslash ( mostly for \" )
  75          $t_qpair_re = "\\\\[$t_char]";
  76  
  77          # a complete quoted string - " characters with valid characters or
  78          #  backslash-escaped characters between them
  79          $t_quoted_string_re = "(?:\"(?:$t_qtext_re|$t_qpair_re)*\")";
  80  
  81          # an unquoted atom (anything that isn't a control char, a space, or a
  82          #  special char)
  83          $t_atom_re  = "(?:[^$t_ctl$t_space$t_specials]+)";
  84  
  85          # a domain ref is an atom
  86          $t_domain_ref_re = $t_atom_re;
  87  
  88          # the characters in a domain literal can be anything except: [ ] \ \r
  89          $t_dtext_re = "[^\\[\\]\\\\\\r]";
  90          # a domain-literal is a sequence of characters or escaped pairs inside
  91          #  square brackets
  92          $t_domain_literal_re = "\\[(?:$t_dtext_re|$t_qpair_re)*\\]";
  93          # a subdomain is a domain ref or a domain literal
  94          $t_sub_domain_re = "(?:$t_domain_ref_re|$t_domain_literal_re)";
  95          # a domain is at least one subdomain, with optional further subdomains
  96          #  separated by periods.  eg: '[1.2.3.4]' or 'foo.bar'
  97          $t_domain_re = "$t_sub_domain_re(?:\.$t_sub_domain_re)*";
  98  
  99          # a word is either quoted string or an atom
 100          $t_word_re = "(?:$t_atom_re|$t_quoted_string_re)";
 101  
 102          # the local part of the address spec (the mailbox name)
 103          #  is one or more words separated by periods
 104          $t_local_part_re = "$t_word_re(?:\.$t_word_re)*";
 105  
 106          # the address spec is made up of a local part, and @ symbol,
 107          #  and a domain
 108          $t_addr_spec_re = "/^($t_local_part_re)\@($t_domain_re)$/";
 109  
 110          return $t_addr_spec_re;
 111      }
 112      # --------------------
 113      # check to see that the format is valid and that the mx record exists
 114  	function email_is_valid( $p_email ) {
 115          # if we don't validate then just accept
 116          if ( OFF == config_get( 'validate_email' ) ) {
 117              return true;
 118          }
 119  
 120          if ( is_blank( $p_email ) && ON == config_get( 'allow_blank_email' ) ) {
 121              return true;
 122          }
 123  
 124          # Use a regular expression to check to see if the email is in valid format
 125          #  x-xx.xxx@yyy.zzz.abc etc.
 126          if ( preg_match( email_get_rfc822_regex(), $p_email, $t_check ) ) {
 127              $t_local = $t_check[1];
 128              $t_domain = $t_check[2];
 129  
 130              # see if we're limited to one domain
 131              if ( ON == config_get( 'limit_email_domain' ) ) {
 132                  if ( 0 != strcasecmp( $t_limit_email_domain, $t_domain ) ) {
 133                      return false;
 134                  }
 135              }
 136  
 137              if ( preg_match( '/\\[(\d+)\.(\d+)\.(\d+)\.(\d+)\\]/', $t_domain, $t_check ) ) {
 138                  # Handle domain-literals of the form '[1.2.3.4]'
 139                  #  as long as each segment is less than 255, we're ok
 140                  if ( $t_check[1] <= 255 &&
 141                       $t_check[2] <= 255 &&
 142                       $t_check[3] <= 255 &&
 143                       $t_check[4] <= 255 ) {
 144                      return true;
 145                  }
 146              } else if ( ON == config_get( 'check_mx_record' ) ) {
 147                  # Check for valid mx records
 148                  if ( getmxrr( $t_domain, $temp ) ) {
 149                      return true;
 150                  } else {
 151                      $host = $t_domain . '.';
 152  
 153                      # for no mx record... try dns check
 154                      if ( checkdnsrr( $host, 'ANY' ) ) {
 155                          return true;
 156                      }
 157                  }
 158              } else {
 159                  # Email format was valid but did't check for valid mx records
 160                  return true;
 161              }
 162          }
 163  
 164          # Everything failed.  The email is invalid
 165          return false;
 166      }
 167      # --------------------
 168      # Check if the email address is valid
 169      #  return true if it is, trigger an ERROR if it isn't
 170  	function email_ensure_valid( $p_email ) {
 171          if ( !email_is_valid( $p_email ) ) {
 172              trigger_error( ERROR_EMAIL_INVALID, ERROR );
 173          }
 174      }
 175  
 176      # --------------------
 177      # Check if the email address is disposable
 178  	function email_is_disposable( $p_email ) {
 179          return DisposableEmailChecker::is_disposable_email( $p_email ); 
 180      }
 181  
 182      # --------------------
 183      # Check if the email address is disposable
 184  	function email_ensure_not_disposable( $p_email ) {
 185          if ( email_is_disposable( $p_email ) ) {
 186              trigger_error( ERROR_EMAIL_DISPOSABLE, ERROR );
 187          }
 188      }
 189  
 190      # --------------------
 191      # email_notify_flag
 192      # Get the value associated with the specific action and flag.
 193      # For example, you can get the value associated with notifying "admin"
 194      # on action "new", i.e. notify administrators on new bugs which can be
 195      # ON or OFF.
 196  	function email_notify_flag( $action, $flag ) {
 197          $t_notify_flags = config_get( 'notify_flags' );
 198          $t_default_notify_flags = config_get( 'default_notify_flags' );
 199          if ( isset ( $t_notify_flags[$action][$flag] ) ) {
 200              return $t_notify_flags[$action][$flag];
 201          } elseif ( isset ( $t_default_notify_flags[$flag] ) ) {
 202              return $t_default_notify_flags[$flag];
 203          }
 204  
 205          return OFF;
 206      }
 207  
 208      # @@@ yarick123: email_collect_recipients(...) will be completely rewritten to provide additional
 209      #     information such as language, user access,..
 210      # @@@ yarick123:sort recipients list by language to reduce switches between different languages
 211  	function email_collect_recipients( $p_bug_id, $p_notify_type ) {
 212          $c_bug_id = db_prepare_int( $p_bug_id );
 213  
 214          $t_recipients = array();
 215  
 216          # add Reporter
 217          if ( ON == email_notify_flag( $p_notify_type, 'reporter' ) ) {
 218              $t_reporter_id = bug_get_field( $p_bug_id, 'reporter_id' );
 219              $t_recipients[$t_reporter_id] = true;
 220              log_event( LOG_EMAIL_RECIPIENT, "bug=$p_bug_id, add reporter=$t_reporter_id" );
 221          }
 222  
 223          # add Handler
 224          if ( ON == email_notify_flag( $p_notify_type, 'handler' )) {
 225              $t_handler_id = bug_get_field( $p_bug_id, 'handler_id' );
 226              
 227              if ( $t_handler_id > 0 ) {
 228                  $t_recipients[$t_handler_id] = true;
 229                  log_event( LOG_EMAIL_RECIPIENT, "bug=$p_bug_id, add handler=$t_handler_id" );
 230              }
 231          }
 232  
 233          $t_project_id = bug_get_field( $p_bug_id, 'project_id' );
 234  
 235          # add users monitoring the bug
 236          $t_bug_monitor_table = config_get( 'mantis_bug_monitor_table' );
 237          if ( ON == email_notify_flag( $p_notify_type, 'monitor' ) ) {
 238              $query = "SELECT DISTINCT user_id
 239                        FROM $t_bug_monitor_table
 240                        WHERE bug_id=$c_bug_id";
 241              $result = db_query( $query );
 242  
 243              $count = db_num_rows( $result );
 244              for ( $i=0 ; $i < $count ; $i++ ) {
 245                  $t_user_id = db_result( $result, $i );
 246                  $t_recipients[$t_user_id] = true;
 247                  log_event( LOG_EMAIL_RECIPIENT, "bug=$p_bug_id, add monitor=$t_user_id" );
 248              }
 249          }
 250  
 251          # add users who contributed bugnotes
 252          $t_bugnote_id = bugnote_get_latest_id( $p_bug_id );
 253          $t_bugnote_view = bugnote_get_field( $t_bugnote_id, 'view_state' );
 254          $t_bugnote_date = db_unixtimestamp( bugnote_get_field( $t_bugnote_id, 'last_modified' ) );
 255          $t_bug_date = bug_get_field( $p_bug_id, 'last_updated' );
 256  
 257          $t_bugnote_table = config_get( 'mantis_bugnote_table' );
 258          if ( ON == email_notify_flag( $p_notify_type, 'bugnotes' ) ) {
 259              $query = "SELECT DISTINCT reporter_id
 260                        FROM $t_bugnote_table
 261                        WHERE bug_id = $c_bug_id";
 262              $result = db_query( $query );
 263  
 264              $count = db_num_rows( $result );
 265              for( $i=0 ; $i < $count ; $i++ ) {
 266                  $t_user_id = db_result( $result, $i );
 267                  $t_recipients[$t_user_id] = true;
 268                  log_event( LOG_EMAIL_RECIPIENT, "bug=$p_bug_id, add note author=$t_user_id" );
 269              }
 270          }
 271  
 272          # add project users who meet the thresholds
 273          $t_bug_is_private = bug_get_field( $p_bug_id, 'view_state' ) == VS_PRIVATE;
 274          $t_threshold_min = email_notify_flag( $p_notify_type, 'threshold_min' );
 275          $t_threshold_max = email_notify_flag( $p_notify_type, 'threshold_max' );
 276          $t_threshold_users = project_get_all_user_rows( $t_project_id, $t_threshold_min );
 277          foreach( $t_threshold_users as $t_user ) {
 278              if ( $t_user['access_level'] <= $t_threshold_max ) {
 279                  if ( !$t_bug_is_private || access_compare_level( $t_user['access_level'], config_get( 'private_bug_threshold' ) ) ) {
 280                      $t_recipients[$t_user['id']] = true;
 281                      log_event( LOG_EMAIL_RECIPIENT, "bug=$p_bug_id, add project user=" . $t_user['id'] );
 282                  }
 283              }
 284          }
 285  
 286          # set up to eliminate unwanted users
 287          #  get list of status values that are not covered specifically in the prefs
 288          #  These are handled by email_on_status generically
 289          #  @@@ thraxisp note that email_on_assigned was co-opted to handle change in handler
 290          $t_status_change = get_enum_to_array( config_get( 'status_enum_string' ) );
 291          unset( $t_status_change[NEW_] );
 292          unset( $t_status_change[FEEDBACK] );
 293          unset( $t_status_change[RESOLVED] );
 294          unset( $t_status_change[CLOSED] );
 295  
 296          if ( 'owner' == $p_notify_type ) {
 297              $t_pref_field = 'email_on_assigned';
 298          } else if ( in_array( $p_notify_type, $t_status_change ) ) {
 299              $t_pref_field = 'email_on_status';
 300          } else {
 301              $t_pref_field = 'email_on_' . $p_notify_type;
 302          }
 303          $t_user_pref_table = config_get( 'mantis_user_pref_table' );
 304          if ( !db_field_exists( $t_pref_field, $t_user_pref_table ) ) {
 305              $t_pref_field = false;
 306          }
 307  
 308          # @@@ we could optimize by modifiying user_cache() to take an array
 309          #  of user ids so we could pull them all in.  We'll see if it's necessary
 310          $t_final_recipients = array();
 311          # Check whether users should receive the emails
 312          # and put email address to $t_recipients[user_id]
 313          foreach ( $t_recipients as $t_id => $t_ignore ) {
 314              # Possibly eliminate the current user
 315              if ( ( auth_get_current_user_id() == $t_id ) &&
 316                   ( OFF == config_get( 'email_receive_own' ) ) ) {
 317                  log_event( LOG_EMAIL_RECIPIENT, "bug=$p_bug_id, drop $t_id (own)" );
 318                  continue;
 319              }
 320  
 321              # Eliminate users who don't exist anymore or who are disabled
 322              if ( !user_exists( $t_id ) ||
 323                   !user_is_enabled( $t_id ) ) {
 324                  log_event( LOG_EMAIL_RECIPIENT, "bug=$p_bug_id, drop $t_id (disabled)" );
 325                  continue;
 326              }
 327  
 328              # Exclude users who have this notification type turned off
 329              if ( $t_pref_field ) {
 330                  $t_notify = user_pref_get_pref( $t_id, $t_pref_field );
 331                  if ( OFF == $t_notify ) {
 332                      log_event( LOG_EMAIL_RECIPIENT, "bug=$p_bug_id, drop $t_id (pref $t_pref_field off)" );
 333                      continue;
 334                  } else {
 335                      # Users can define the severity of an issue before they are emailed for
 336                      # each type of notification
 337                      $t_min_sev_pref_field = $t_pref_field . '_min_severity';
 338                      $t_min_sev_notify     = user_pref_get_pref( $t_id, $t_min_sev_pref_field );
 339                      $t_bug_severity       = bug_get_field( $p_bug_id, 'severity' );
 340  
 341                      if ( $t_bug_severity < $t_min_sev_notify ) {
 342                          log_event( LOG_EMAIL_RECIPIENT, "bug=$p_bug_id, drop $t_id (pref threshold)" );
 343                          continue;
 344                      }
 345                  }
 346              }
 347  
 348              # check that user can see bugnotes if the last update included a bugnote
 349              if ( $t_bug_date == $t_bugnote_date ) {
 350                  if ( !access_has_bugnote_level( VIEWER, $t_bugnote_id, $t_id ) ) {
 351                          log_event( LOG_EMAIL_RECIPIENT, "bug=$p_bug_id, drop $t_id (access level)" );
 352                      continue;
 353                  }
 354              }
 355  
 356              # Finally, let's get their emails, if they've set one
 357              $t_email = user_get_email( $t_id );
 358              if ( is_blank( $t_email ) ) {
 359                  log_event( LOG_EMAIL_RECIPIENT, "bug=$p_bug_id, drop $t_id (no email)" );
 360              } else {
 361                  # @@@ we could check the emails for validity again but I think
 362                  #   it would be too slow
 363                  $t_final_recipients[$t_id] = $t_email;
 364              }
 365          }
 366  
 367          return $t_final_recipients;
 368      }
 369  
 370      # --------------------
 371      # Send password to user
 372  	function email_signup( $p_user_id, $p_password, $p_confirm_hash ) {
 373  
 374          if ( ( OFF == config_get( 'send_reset_password' ) ) || ( OFF == config_get( 'enable_email_notification' ) ) ) {
 375                      return;
 376          }
 377  
 378  #        @@@ thraxisp - removed to address #6084 - user won't have any settings yet,
 379  #       use same language as display for the email
 380  #       lang_push( user_pref_get_language( $p_user_id ) );
 381  
 382          # retrieve the username and email
 383          $t_username = user_get_field( $p_user_id, 'username' );
 384          $t_email = user_get_email( $p_user_id );
 385  
 386          # Build Welcome Message
 387          $t_subject = '[' . config_get( 'window_title' ) . '] ' . lang_get( 'new_account_subject' );
 388  
 389          $t_message = lang_get( 'new_account_greeting' ) . $t_username .
 390                          lang_get( 'new_account_greeting2' ) . " \n\n" .
 391                          string_get_confirm_hash_url( $p_user_id, $p_confirm_hash ) . " \n\n" .
 392                          lang_get( 'new_account_message' ) .
 393                          lang_get( 'new_account_do_not_reply' );
 394  
 395          # Send signup email regardless of mail notification pref
 396          # or else users won't be able to sign up
 397          if( !is_blank( $t_email ) ) {
 398              email_store( $t_email, $t_subject, $t_message );
 399              log_event( LOG_EMAIL, "signup=$t_email, hash=$p_confirm_hash, id=$p_user_id" );
 400  
 401              if ( OFF == config_get( 'email_send_using_cronjob' ) ) {
 402                  email_send_all();
 403              }
 404          }
 405  
 406  #        lang_pop(); # see above
 407      }
 408  
 409      # --------------------
 410      # Send confirm_hash url to user forgets the password
 411  	function email_send_confirm_hash_url( $p_user_id, $p_confirm_hash ) {
 412          if ( ( OFF == config_get( 'send_reset_password' ) ) || ( OFF == config_get( 'enable_email_notification' ) ) ) {
 413              return;
 414          }
 415  
 416          lang_push( user_pref_get_language( $p_user_id ) );
 417  
 418          # retrieve the username and email
 419          $t_username = user_get_field( $p_user_id, 'username' );
 420          $t_email = user_get_email( $p_user_id );
 421  
 422          $t_subject = '[' . config_get( 'window_title' ) . '] ' . lang_get( 'lost_password_subject' );
 423  
 424          $t_message = lang_get( 'reset_request_msg' ) . " \n\n" .
 425                          string_get_confirm_hash_url( $p_user_id, $p_confirm_hash ) . " \n\n" .
 426                          lang_get( 'new_account_username' ) . $t_username . " \n" .
 427                          lang_get( 'new_account_IP' ) . $_SERVER["REMOTE_ADDR"] . " \n\n" .
 428                          lang_get( 'new_account_do_not_reply' );
 429  
 430          # Send password reset regardless of mail notification prefs
 431          # or else users won't be able to receive their reset pws
 432          if( !is_blank( $t_email ) ) {
 433              email_store( $t_email, $t_subject, $t_message );
 434              log_event( LOG_EMAIL, "password_reset=$t_email" );
 435  
 436              if ( OFF == config_get( 'email_send_using_cronjob' ) ) {
 437                  email_send_all();
 438              }
 439          }
 440  
 441          lang_pop();
 442      }
 443  
 444      # --------------------
 445      # notify the selected group a new user has signup
 446  	function email_notify_new_account( $p_username, $p_email ) {
 447          global $g_path;
 448  
 449          $t_threshold_min = config_get( 'notify_new_user_created_threshold_min' );
 450          $t_threshold_users = project_get_all_user_rows( ALL_PROJECTS, $t_threshold_min );
 451  
 452          foreach( $t_threshold_users as $t_user ) {
 453              lang_push( user_pref_get_language( $t_user['id'] ) );
 454  
 455              $t_recipient_email = user_get_email( $t_user['id'] );
 456              $t_subject = '[' . config_get( 'window_title' ) . '] ' . lang_get( 'new_account_subject' );
 457  
 458              $t_message = lang_get( 'new_account_signup_msg' ) . " \n\n" .
 459                          lang_get( 'new_account_username' ) . $p_username . " \n" .
 460                          lang_get( 'new_account_email' ) . $p_email . " \n" .
 461                          lang_get( 'new_account_IP' ) . $_SERVER["REMOTE_ADDR"] . " \n" .
 462                          $g_path . "\n\n" .
 463                          lang_get( 'new_account_do_not_reply' );
 464  
 465              if( !is_blank( $t_recipient_email ) ) {
 466                  email_store( $t_recipient_email, $t_subject, $t_message );
 467                  log_event( LOG_EMAIL, "new_account_notify=$t_recipient_email" );
 468  
 469                  if ( OFF == config_get( 'email_send_using_cronjob' ) ) {
 470                      email_send_all();
 471                  }
 472              }
 473  
 474              lang_pop();
 475          }
 476      }
 477  
 478      # --------------------
 479      # send a generic email
 480      # $p_notify_type: use check who she get notified of such event.
 481      # $p_message_id: message id to be translated and included at the top of the email message.
 482      # Return false if it were problems sending email
 483  	function email_generic( $p_bug_id, $p_notify_type, $p_message_id = null, $p_header_optional_params = null ) {
 484          $t_ok = true;
 485          if ( ON === config_get( 'enable_email_notification' ) ) {
 486              ignore_user_abort( true );
 487  
 488              # @@@ yarick123: email_collect_recipients(...) will be completely rewritten to provide additional
 489              #     information such as language, user access,..
 490              # @@@ yarick123:sort recipients list by language to reduce switches between different languages
 491              $t_recipients = email_collect_recipients( $p_bug_id, $p_notify_type );
 492  
 493              $t_project_id = bug_get_field( $p_bug_id, 'project_id' );
 494              if ( is_array( $t_recipients ) ) {
 495                  log_event( LOG_EMAIL, sprintf("bug=%d, type=%s, msg=%s, recipients=(%s)", $p_bug_id, $p_notify_type, $p_message_id, implode( '. ', $t_recipients ) ) );
 496  
 497                  # send email to every recipient
 498                  foreach ( $t_recipients as $t_user_id => $t_user_email ) {
 499                      # load (push) user language here as build_visible_bug_data assumes current language
 500                      lang_push( user_pref_get_language( $t_user_id, $t_project_id ) );
 501  
 502                      $t_visible_bug_data = email_build_visible_bug_data( $t_user_id, $p_bug_id, $p_message_id );
 503                      $t_ok = email_bug_info_to_one_user( $t_visible_bug_data, $p_message_id, $t_project_id, $t_user_id, $p_header_optional_params ) && $t_ok;
 504                      
 505                      lang_pop();
 506                  }
 507              }
 508          }
 509  
 510          if ( OFF == config_get( 'email_send_using_cronjob' ) ) {
 511              email_send_all();
 512          }
 513  
 514          return $t_ok;
 515      }
 516  
 517      # --------------------
 518      # send notices when a relationship is ADDED
 519      # MASC RELATIONSHIP
 520  	function email_relationship_added( $p_bug_id, $p_related_bug_id, $p_rel_type ) {
 521          $t_opt = array();
 522          $t_opt[] = bug_format_id( $p_related_bug_id );
 523          global $g_relationships;
 524          if ( !isset( $g_relationships[ $p_rel_type ] ) ) {
 525              trigger_error( ERROR_RELATIONSHIP_NOT_FOUND, ERROR );
 526          }
 527          email_generic( $p_bug_id, 'relation', $g_relationships[ $p_rel_type ][ '#notify_added' ], $t_opt );
 528      }
 529  
 530      # --------------------
 531      # send notices when a relationship is DELETED
 532      # MASC RELATIONSHIP
 533  	function email_relationship_deleted( $p_bug_id, $p_related_bug_id, $p_rel_type ) {
 534          $t_opt = array();
 535          $t_opt[] = bug_format_id( $p_related_bug_id );
 536          global $g_relationships;
 537          if ( !isset( $g_relationships[ $p_rel_type ] ) ) {
 538              trigger_error( ERROR_RELATIONSHIP_NOT_FOUND, ERROR );
 539          }
 540          email_generic( $p_bug_id, 'relation', $g_relationships[ $p_rel_type ][ '#notify_deleted' ], $t_opt );
 541      }
 542  
 543      # --------------------
 544      # send notices to all the handlers of the parent bugs when a child bug is RESOLVED
 545      # MASC RELATIONSHIP
 546  	function email_relationship_child_resolved( $p_bug_id ) {
 547          email_relationship_child_resolved_closed( $p_bug_id, 'email_notification_title_for_action_relationship_child_resolved' );
 548      }
 549  
 550      # --------------------
 551      # send notices to all the handlers of the parent bugs when a child bug is CLOSED
 552      # MASC RELATIONSHIP
 553  	function email_relationship_child_closed( $p_bug_id ) {
 554          email_relationship_child_resolved_closed( $p_bug_id, 'email_notification_title_for_action_relationship_child_closed' );
 555      }
 556  
 557      # --------------------
 558      # send notices to all the handlers of the parent bugs still open when a child bug is resolved/closed
 559      # MASC RELATIONSHIP
 560  	function email_relationship_child_resolved_closed( $p_bug_id, $p_message_id ) {
 561          # retrieve all the relationships in which the bug is the destination bug
 562          $t_relationship = relationship_get_all_dest( $p_bug_id );
 563          $t_relationship_count = count( $t_relationship );
 564          if ( $t_relationship_count == 0 ) {
 565              # no parent bug found
 566              return;
 567          }
 568  
 569          for ( $i = 0 ; $i < $t_relationship_count ; $i++ ) {
 570              if ( $t_relationship[$i]->type == BUG_DEPENDANT ) {
 571                  $t_src_bug_id = $t_relationship[$i]->src_bug_id;
 572                  $t_status = bug_get_field( $t_src_bug_id, 'status' );
 573                  if ( $t_status < config_get( 'bug_resolved_status_threshold' ) ) {
 574                      # sent the notification just for parent bugs not resolved/closed
 575                      $t_opt = array();
 576                      $t_opt[] = bug_format_id( $p_bug_id );
 577                      email_generic( $t_src_bug_id, 'handler', $p_message_id, $t_opt );
 578                  }
 579              }
 580          }
 581      }
 582  
 583      # --------------------
 584      # send notices when a bug is sponsored
 585  	function email_sponsorship_added( $p_bug_id ) {
 586          email_generic( $p_bug_id, 'sponsor', 'email_notification_title_for_action_sponsorship_added' );
 587      }
 588  
 589      # --------------------
 590      # send notices when a sponsorship is modified
 591  	function email_sponsorship_updated( $p_bug_id ) {
 592          email_generic( $p_bug_id, 'sponsor', 'email_notification_title_for_action_sponsorship_updated' );
 593      }
 594  
 595      # --------------------
 596      # send notices when a sponsorship is deleted
 597  	function email_sponsorship_deleted( $p_bug_id ) {
 598          email_generic( $p_bug_id, 'sponsor', 'email_notification_title_for_action_sponsorship_deleted' );
 599      }
 600  
 601      # --------------------
 602      # send notices when a new bug is added
 603  	function email_new_bug( $p_bug_id ) {
 604          email_generic( $p_bug_id, 'new', 'email_notification_title_for_action_bug_submitted' );
 605      }
 606      # --------------------
 607      # send notices when a new bugnote
 608  	function email_bugnote_add( $p_bug_id ) {
 609          email_generic( $p_bug_id, 'bugnote', 'email_notification_title_for_action_bugnote_submitted' );
 610      }
 611      # --------------------
 612      # send notices when a bug is RESOLVED
 613  	function email_resolved( $p_bug_id ) {
 614          email_generic( $p_bug_id, 'resolved', 'email_notification_title_for_status_bug_resolved' );
 615      }
 616      # --------------------
 617      # send notices when a bug is CLOSED
 618  	function email_close( $p_bug_id ) {
 619          email_generic( $p_bug_id, 'closed', 'email_notification_title_for_status_bug_closed' );
 620      }
 621      # --------------------
 622      # send notices when a bug is REOPENED
 623  	function email_reopen( $p_bug_id ) {
 624          email_generic( $p_bug_id, 'reopened', 'email_notification_title_for_action_bug_reopened' );
 625      }
 626      # --------------------
 627      # send notices when a bug is ASSIGNED
 628  	function email_assign( $p_bug_id ) {
 629          email_generic( $p_bug_id, 'owner', 'email_notification_title_for_action_bug_assigned' );
 630      }
 631      # --------------------
 632      # send notices when a bug is DELETED
 633  	function email_bug_deleted( $p_bug_id ) {
 634          email_generic( $p_bug_id, 'deleted', 'email_notification_title_for_action_bug_deleted' );
 635      }
 636      # --------------------
 637  	function email_store( $p_recipient, $p_subject, $p_message, $p_headers = null ) {
 638          $t_recipient = trim( $p_recipient );
 639          $t_subject   = string_email( trim( $p_subject ) );
 640          $t_message   = string_email_links( trim( $p_message ) );
 641  
 642          # short-circuit if no recipient is defined, or email disabled
 643          # note that this may cause signup messages not to be sent
 644  
 645          if ( is_blank( $p_recipient ) || ( OFF == config_get( 'enable_email_notification' ) ) ) {
 646              return;
 647          }
 648  
 649          $t_email_data = new EmailData;
 650  
 651          $t_email_data->email = $t_recipient;
 652          $t_email_data->subject = $t_subject;
 653          $t_email_data->body = $t_message;
 654          $t_email_data->metadata = array();
 655          $t_email_data->metadata['headers'] = $p_headers === null ? array() : $p_headers;
 656          $t_email_data->metadata['priority'] = config_get( 'mail_priority' );               # Urgent = 1, Not Urgent = 5, Disable = 0
 657          $t_email_data->metadata['charset'] =  lang_get( 'charset', lang_get_current() );
 658  
 659          $t_hostname = '';
 660          $t_server = isset( $_SERVER ) ? $_SERVER : $HTTP_SERVER_VARS;
 661          if ( isset( $t_server['SERVER_NAME'] ) ) {
 662              $t_hostname = $t_server['SERVER_NAME'];
 663          } else {
 664              $t_address = explode( '@', config_get( 'from_email' ) );
 665              if ( isset( $t_address[1] ) ) {
 666                  $t_hostname = $t_address[1];
 667              }
 668          }
 669          $t_email_data->metadata['hostname'] = $t_hostname;
 670  
 671          $t_email_id = email_queue_add( $t_email_data );
 672          
 673          return $t_email_id; 
 674      }
 675  
 676      # --------------------
 677      # This function sends all the emails that are stored in the queue.  If a failure occurs, then the
 678      # function exists.  This function will be called after storing emails in case of synchronous
 679      # emails, or will be called from a cronjob in case of asynchronous emails.
 680      # @@@ In case of synchronous email sending, we may get a race condition where two requests send the same email.
 681  	function email_send_all() {
 682          $t_ids = email_queue_get_ids();
 683  
 684          $t_emails_recipients_failed = array();
 685          $t_start = microtime_float();
 686          foreach ( $t_ids as $t_id ) {
 687              $t_email_data = email_queue_get( $t_id );
 688  
 689              # check if email was not found.  This can happen if another request picks up the email first and sends it.
 690              if ( $t_email_data === false ) {
 691                  continue;
 692              }
 693  
 694              # if unable to place the email in the email server queue, then the connection to the server is down,
 695              # and hence no point to continue trying with the rest of the emails.
 696              if ( !email_send( $t_email_data ) ) {
 697                  if ( microtime_float() - $t_start > 5)
 698                      break;
 699                  else 
 700                      continue;
 701              }
 702          }
 703      }
 704  
 705      # --------------------
 706      # This function sends an email message based on the supplied email data.
 707  	function email_send( $p_email_data ) {
 708          global $g_phpMailer_smtp;
 709  
 710          $t_email_data = $p_email_data;
 711  
 712          $t_recipient = trim( $t_email_data->email );
 713          $t_subject   = string_email( trim( $t_email_data->subject ) );
 714          $t_message   = string_email_links( trim( $t_email_data->body ) );
 715  
 716          $t_debug_email = config_get( 'debug_email' );
 717  
 718          # Visit http://phpmailer.sourceforge.net
 719          # if you have problems with phpMailer
 720  
 721          $mail = new PHPMailer;
 722          $mail->PluginDir = PHPMAILER_PATH;
 723          
 724          if ( isset( $t_email_data->metadata['hostname'] ) ) {
 725              $mail->Hostname = $t_email_data->metadata['hostname'];
 726          }
 727  
 728          # @@@ should this be the current language (for the recipient) or the default one (for the user running the command) (thraxisp)
 729          $mail->SetLanguage( lang_get( 'phpmailer_language', config_get( 'default_language' ) ), PHPMAILER_PATH . 'language' . DIRECTORY_SEPARATOR );
 730  
 731          # Select the method to send mail
 732          switch ( config_get( 'phpMailer_method' ) ) {
 733              case 0: $mail->IsMail();
 734                      break;
 735  
 736              case 1: $mail->IsSendmail();
 737                      break;
 738  
 739              case 2: $mail->IsSMTP();
 740                      {
 741                          # SMTP collection is always kept alive
 742                          #
 743                          $mail->SMTPKeepAlive = true;
 744  
 745                          # @@@ yarick123: It is said in phpMailer comments, that phpMailer::smtp has private access.
 746                          # but there is no common method to reset PHPMailer object, so
 747                          # I see the smallest evel - to initialize only one 'private'
 748                          # field phpMailer::smtp in order to reuse smtp connection.
 749  
 750                          if( is_null( $g_phpMailer_smtp ) )  {
 751                              register_shutdown_function( 'email_smtp_close' );
 752                          } else {
 753                              $mail->smtp = $g_phpMailer_smtp;
 754                          }
 755                      }
 756                      break;
 757          }
 758  
 759          $mail->IsHTML( false );              # set email format to plain text
 760          $mail->WordWrap = 80;              # set word wrap to 50 characters
 761          $mail->Priority = $t_email_data->metadata['priority'];  # Urgent = 1, Not Urgent = 5, Disable = 0
 762          $mail->CharSet = $t_email_data->metadata['charset'];
 763          $mail->Host     = config_get( 'smtp_host' );
 764          $mail->From     = config_get( 'from_email' );
 765          $mail->Sender   = escapeshellcmd( config_get( 'return_path_email' ) );
 766          $mail->FromName = config_get( 'from_name');
 767  
 768  
 769          if ( !is_blank( config_get( 'smtp_username' ) ) ) {     # Use SMTP Authentication
 770              $mail->SMTPAuth = true;
 771              $mail->Username = config_get( 'smtp_username' );
 772              $mail->Password = config_get( 'smtp_password' );
 773          }
 774  
 775          if ( OFF !== $t_debug_email ) {
 776              $t_message = 'To: '. $t_recipient . "\n\n" . $t_message;
 777              $mail->AddAddress( $t_debug_email, '' );
 778          } else {
 779              $mail->AddAddress( $t_recipient, '' );
 780          }
 781  
 782          $mail->Subject = $t_subject;
 783          $mail->Body    = make_lf_crlf( "\n" . $t_message );
 784  
 785          if ( isset( $t_email_data->metadata['headers'] ) && is_array( $t_email_data->metadata['headers'] ) ) {
 786              foreach ( $t_email_data->metadata['headers'] as $t_key => $t_value ) {
 787                  $mail->AddCustomHeader( "$t_key: $t_value" );
 788              }
 789          }
 790  
 791          if ( !$mail->Send() ) {
 792              $t_success = false;
 793          } else {
 794              $t_success = true;
 795  
 796              if ( $t_email_data->email_id > 0 ) {
 797                  email_queue_delete( $t_email_data->email_id );
 798              }
 799          }
 800  
 801          if ( !is_null( $mail->smtp ) )  {
 802              # @@@ yarick123: It is said in phpMailer comments, that phpMailer::smtp has private access.
 803              # but there is no common method to reset PHPMailer object, so
 804              # I see the smallest evel - to initialize only one 'private'
 805              # field phpMailer::smtp in order to reuse smtp connection.
 806              $g_phpMailer_smtp = $mail->smtp;
 807          }
 808  
 809          return $t_success;
 810      }
 811  
 812      # --------------------
 813      # closes opened kept alive SMTP connection (if it was opened)
 814  	function email_smtp_close()  {
 815          global $g_phpMailer_smtp;
 816  
 817          if ( !is_null( $g_phpMailer_smtp ) )  {
 818              if ( $g_phpMailer_smtp->Connected() )  {
 819                  $g_phpMailer_smtp->Quit();
 820                  $g_phpMailer_smtp->Close();
 821              }
 822              $g_phpMailer_smtp = null;
 823          }
 824      }
 825      # --------------------
 826      # formats the subject correctly
 827      # we include the project name, bug id, and summary.
 828  	function email_build_subject( $p_bug_id ) {
 829          # grab the project name
 830          $p_project_name = project_get_field( bug_get_field( $p_bug_id, 'project_id' ), 'name' );
 831  
 832          # grab the subject (summary)
 833          $p_subject = bug_get_field( $p_bug_id, 'summary' );
 834  
 835          # padd the bug id with zeros
 836          $p_bug_id = bug_format_id( $p_bug_id );
 837  
 838          return '['.$p_project_name.' '.$p_bug_id.']: '.$p_subject;
 839      }
 840      # --------------------
 841      # clean up LF to CRLF
 842  	function make_lf_crlf( $p_string ) {
 843          $t_string = str_replace( "\n", "\r\n", $p_string );
 844          return str_replace( "\r\r\n", "\r\n", $t_string );
 845      }
 846      # --------------------
 847      # Check limit_email_domain option and append the domain name if it is set
 848  	function email_append_domain( $p_email ) {
 849          $t_limit_email_domain = config_get( 'limit_email_domain' );
 850          if ( $t_limit_email_domain && !is_blank( $p_email ) ) {
 851              $p_email = "$p_email@$t_limit_email_domain";
 852          }
 853  
 854          return $p_email;
 855      }
 856      # --------------------
 857      # Send a bug reminder to each of the given user, or to each user if the first
 858      #  parameter is an array
 859      # return an array of usernames to which the reminder was successfully sent
 860      #
 861      # @@@ I'm not sure this shouldn't return an array of user ids... more work for
 862      #  the caller but cleaner from an API point of view.
 863  	function email_bug_reminder( $p_recipients, $p_bug_id, $p_message ) {
 864  
 865          if ( !is_array( $p_recipients ) ) {
 866              $p_recipients = array( $p_recipients );
 867          }
 868  
 869          $t_project_id = bug_get_field( $p_bug_id, 'project_id' );
 870          $t_sender_id = auth_get_current_user_id();
 871          $t_sender = user_get_name( $t_sender_id );
 872  
 873          $t_subject = email_build_subject( $p_bug_id );
 874          $t_date = date( config_get( 'normal_date_format' ) );
 875          
 876          $result = array();
 877          foreach ( $p_recipients as $t_recipient ) {
 878              lang_push( user_pref_get_language( $t_recipient, $t_project_id ) );
 879  
 880              $t_email = user_get_email( $t_recipient );
 881              $result[] = user_get_name( $t_recipient );
 882  
 883              if ( access_has_project_level( config_get( 'show_user_email_threshold' ), $t_project_id, $t_recipient ) ) {
 884                  $t_sender_email = ' <' . current_user_get_field( 'email' ) . '>' ;
 885              } else {
 886                  $t_sender_email = '';
 887              }
 888              $t_header = "\n" . lang_get( 'on' ) . " $t_date, $t_sender $t_sender_email " .
 889                          lang_get( 'sent_you_this_reminder_about' ) . ": \n\n";
 890              $t_contents = $t_header .
 891                              string_get_bug_view_url_with_fqdn( $p_bug_id, $t_recipient ) .
 892                              " \n\n$p_message";
 893  
 894              if( ON == config_get( 'enable_email_notification' ) ) {
 895                  email_store( $t_email, $t_subject, $t_contents );
 896              }
 897  
 898              lang_pop();
 899          }
 900  
 901          if ( OFF == config_get( 'email_send_using_cronjob' ) ) {
 902              email_send_all();
 903          }
 904  
 905          return $result;
 906      }
 907  
 908      # --------------------
 909      # Send bug info to given user
 910      # return true on success
 911  	function email_bug_info_to_one_user( $p_visible_bug_data, $p_message_id, $p_project_id, $p_user_id, $p_header_optional_params = null ) {
 912  
 913          $t_user_email = user_get_email( $p_user_id );
 914  
 915          # check whether email should be sent
 916          # @@@ can be email field empty? if yes - then it should be handled here
 917          if ( ON !== config_get( 'enable_email_notification' ) || is_blank( $t_user_email ) ) {
 918              return true;
 919          }
 920  
 921          # build subject
 922          $t_subject = '['.$p_visible_bug_data['email_project'].' '
 923                          .bug_format_id( $p_visible_bug_data['email_bug'] )
 924                      .']: '.$p_visible_bug_data['email_summary'];
 925  
 926          # build message
 927  
 928          $t_message = lang_get_defaulted( $p_message_id, null );
 929  
 930          if ( is_array( $p_header_optional_params ) ) {
 931              $t_message = vsprintf( $t_message, $p_header_optional_params );
 932          }
 933  
 934          if ( ( $t_message !== null ) && ( !is_blank( $t_message ) ) ) {
 935              $t_message .= " \n";
 936          }
 937  
 938          $t_message .= email_format_bug_message(  $p_visible_bug_data );
 939  
 940          # build headers
 941          $t_bug_id = $p_visible_bug_data['email_bug'];
 942          $t_message_md5 = md5( $t_bug_id . $p_visible_bug_data['email_date_submitted'] );
 943          $t_mail_headers = array( 'keywords' => $p_visible_bug_data['set_category'] );
 944          if ( $p_message_id == 'email_notification_title_for_action_bug_submitted' ) {
 945              $t_mail_headers['Message-ID'] = "<{$t_message_md5}>";
 946          } else {
 947              $t_mail_headers['In-Reply-To'] = "<{$t_message_md5}>";
 948          }
 949  
 950          # send mail
 951          # PRINT '<br />email_bug_info::Sending email to :'.$t_user_email;
 952          $t_ok = email_store( $t_user_email, $t_subject, $t_message, $t_mail_headers );
 953  
 954          return $t_ok;
 955      }
 956  
 957      # --------------------
 958      # Build the bug info part of the message
 959  	function email_format_bug_message( $p_visible_bug_data ) {
 960  
 961          $t_normal_date_format = config_get( 'normal_date_format' );
 962          $t_complete_date_format = config_get( 'complete_date_format' );
 963  
 964          $t_email_separator1 = config_get( 'email_separator1' );
 965          $t_email_separator2 = config_get( 'email_separator2' );
 966          $t_email_padding_length = config_get( 'email_padding_length' );
 967  
 968          $t_status = $p_visible_bug_data['email_status'];
 969  
 970          $p_visible_bug_data['email_date_submitted'] = date( $t_complete_date_format, $p_visible_bug_data['email_date_submitted'] );
 971          $p_visible_bug_data['email_last_modified']   = date( $t_complete_date_format, $p_visible_bug_data['email_last_modified'] );
 972  
 973          $p_visible_bug_data['email_status'] = get_enum_element( 'status', $t_status );
 974          $p_visible_bug_data['email_severity'] = get_enum_element( 'severity', $p_visible_bug_data['email_severity'] );
 975          $p_visible_bug_data['email_priority'] = get_enum_element( 'priority', $p_visible_bug_data['email_priority'] );
 976          $p_visible_bug_data['email_reproducibility'] = get_enum_element( 'reproducibility', $p_visible_bug_data['email_reproducibility'] );
 977  
 978          $t_message = $t_email_separator1 . " \n";
 979  
 980          if ( isset( $p_visible_bug_data['email_bug_view_url'] ) ) {
 981              $t_message .= $p_visible_bug_data['email_bug_view_url'] . " \n";
 982              $t_message .= $t_email_separator1 . " \n";
 983          }
 984  
 985          $t_message .= email_format_attribute( $p_visible_bug_data, 'email_reporter' );
 986          $t_message .= email_format_attribute( $p_visible_bug_data, 'email_handler' );
 987          $t_message .= $t_email_separator1 . " \n";
 988          $t_message .= email_format_attribute( $p_visible_bug_data, 'email_project' );
 989          $t_message .= email_format_attribute( $p_visible_bug_data, 'email_bug' );
 990          $t_message .= email_format_attribute( $p_visible_bug_data, 'email_category' );
 991          $t_message .= email_format_attribute( $p_visible_bug_data, 'email_reproducibility' );
 992          $t_message .= email_format_attribute( $p_visible_bug_data, 'email_severity' );
 993          $t_message .= email_format_attribute( $p_visible_bug_data, 'email_priority' );
 994          $t_message .= email_format_attribute( $p_visible_bug_data, 'email_status' );
 995          $t_message .= email_format_attribute( $p_visible_bug_data, 'email_target_version' );
 996  
 997          # custom fields formatting
 998          foreach( $p_visible_bug_data['custom_fields'] as $t_custom_field_name => $t_custom_field_data ) {
 999              $t_message .= str_pad( lang_get_defaulted( $t_custom_field_name, null ) . ': ', $t_email_padding_length, ' ', STR_PAD_RIGHT );
1000              $t_message .= string_custom_field_value_for_email ( $t_custom_field_data['value'], $t_custom_field_data['type'] );
1001              $t_message .= " \n";
1002          } # end foreach custom field
1003  
1004          if ( config_get( 'bug_resolved_status_threshold' ) <= $t_status ) {
1005              $p_visible_bug_data['email_resolution'] = get_enum_element( 'resolution', $p_visible_bug_data['email_resolution'] );
1006              $t_message .= email_format_attribute( $p_visible_bug_data, 'email_resolution' );
1007              $t_message .= email_format_attribute( $p_visible_bug_data, 'email_duplicate' );
1008              $t_message .= email_format_attribute( $p_visible_bug_data, 'email_fixed_in_version' );
1009          }
1010          $t_message .= $t_email_separator1 . " \n";
1011  
1012          $t_message .= email_format_attribute( $p_visible_bug_data, 'email_date_submitted' );
1013          $t_message .= email_format_attribute( $p_visible_bug_data, 'email_last_modified' );
1014          $t_message .= $t_email_separator1 . " \n";
1015  
1016          $t_message .= email_format_attribute( $p_visible_bug_data, 'email_summary' );
1017  
1018          $t_message .= lang_get( 'email_description' ) . ": \n".wordwrap( $p_visible_bug_data['email_description'] )."\n";
1019  
1020          # MASC RELATIONSHIP
1021          if ( ON == config_get( 'enable_relationship' ) ) {
1022              if (isset( $p_visible_bug_data['relations'] )) {
1023                  $t_message .= $p_visible_bug_data['relations'];
1024              }
1025          }
1026          # MASC RELATIONSHIP
1027  
1028          # Sponsorship
1029          if ( isset( $p_visible_bug_data['sponsorship_total'] ) && ( $p_visible_bug_data['sponsorship_total'] > 0 ) ) {
1030              $t_message .= $t_email_separator1 . " \n";
1031              $t_message .= sprintf( lang_get( 'total_sponsorship_amount' ), sponsorship_format_amount( $p_visible_bug_data['sponsorship_total'] ) ) . "\n" . "\n";
1032  
1033              if ( isset( $p_visible_bug_data['sponsorships'] ) ) {
1034                  foreach ( $p_visible_bug_data['sponsorships'] as $t_sponsorship ) {
1035                      $t_date_added = date( config_get( 'normal_date_format' ), $t_sponsorship->date_submitted );
1036  
1037                      $t_message .= $t_date_added . ': ';
1038                      $t_message .= user_get_name( $t_sponsorship->user_id );
1039                      $t_message .= ' (' . sponsorship_format_amount( $t_sponsorship->amount ) . ')' . " \n";
1040                  }
1041              }
1042          }
1043  
1044          $t_message .= $t_email_separator1 . " \n\n";
1045  
1046          # format bugnotes
1047          foreach ( $p_visible_bug_data['bugnotes'] as $t_bugnote ) {
1048              $t_last_modified = date( $t_normal_date_format, $t_bugnote->last_modified );
1049  
1050              $t_formatted_bugnote_id = bugnote_format_id( $t_bugnote->id );
1051              $t_bugnote_link = string_process_bugnote_link ( config_get( 'bugnote_link_tag' ) . $t_bugnote->id, false, false, true );
1052  
1053              $t_time_tracking_minutes = bugnote_get_field ( $t_bugnote->id, 'time_tracking' );
1054              if ( $t_time_tracking_minutes > 0 ) {
1055                  $t_time_tracking = ' ' . lang_get( 'time_tracking' ) . ' ' . db_minutes_to_hhmm( $t_time_tracking_minutes ) . "\n";
1056              } else {
1057                  $t_time_tracking = '';
1058              }
1059  
1060              if ( user_exists( $t_bugnote->reporter_id ) ) {
1061                  $t_access_level = access_get_project_level( null,  $t_bugnote->reporter_id );
1062                  $t_access_level_string = ' (' . get_enum_element( 'access_levels', $t_access_level ) . ') - '; 
1063              } else {
1064                  $t_access_level_string = '';
1065              }
1066  
1067              $t_string = ' (' . $t_formatted_bugnote_id . ') ' . 
1068                  user_get_name( $t_bugnote->reporter_id ) .
1069                  $t_access_level_string .
1070                  $t_last_modified . "\n" .
1071                  $t_time_tracking . ' ' . $t_bugnote_link;
1072  
1073              $t_message .= $t_email_separator2 . " \n";
1074              $t_message .= $t_string . " \n";
1075              $t_message .= $t_email_separator2 . " \n";
1076              $t_message .= wordwrap( $t_bugnote->note ) . " \n\n";
1077          }
1078  
1079          # format history
1080          if ( array_key_exists( 'history', $p_visible_bug_data ) ) {
1081              $t_message .=    lang_get( 'bug_history' ) . " \n";
1082              $t_message .=    str_pad( lang_get( 'date_modified' ), 17 ) .
1083                              str_pad( lang_get( 'username' ), 15 ) .
1084                              str_pad( lang_get( 'field' ), 25 ) .
1085                              str_pad( lang_get( 'change' ), 20 ). " \n";
1086  
1087              $t_message .= $t_email_separator1 . " \n";
1088  
1089              foreach ( $p_visible_bug_data['history'] as $t_raw_history_item ) {
1090                  $t_localized_item = history_localize_item(    $t_raw_history_item['field'],
1091                                                              $t_raw_history_item['type'],
1092                                                              $t_raw_history_item['old_value'],
1093                                                              $t_raw_history_item['new_value'] );
1094  
1095                  $t_message .=    str_pad( date( $t_normal_date_format, $t_raw_history_item['date'] ), 17 ) .
1096                                  str_pad( $t_raw_history_item['username'], 15 ) .
1097                                  str_pad( $t_localized_item['note'], 25 ) .
1098                                  str_pad( $t_localized_item['change'], 20 ) . "\n";
1099              }
1100              $t_message .= $t_email_separator1 . " \n\n";
1101          }
1102  
1103          return $t_message;
1104      }
1105  
1106      # --------------------
1107      # if $p_visible_bug_data contains specified attribute the function
1108      # returns concatenated translated attribute name and original
1109      # attribute value. Else return empty string.
1110  	function email_format_attribute( $p_visible_bug_data, $attribute_id ) {
1111  
1112          if ( array_key_exists( $attribute_id, $p_visible_bug_data ) ) {
1113              return str_pad( lang_get( $attribute_id ) . ': ', config_get( 'email_padding_length' ), ' ', STR_PAD_RIGHT ).$p_visible_bug_data[$attribute_id]."\n";
1114          }
1115          return '';
1116      }
1117  
1118      # --------------------
1119      # Build the bug raw data visible for specified user to be translated and sent by email to the user
1120      # (Filter the bug data according to user access level)
1121      # return array with bug data. See usage in email_format_bug_message(...)
1122  	function email_build_visible_bug_data( $p_user_id, $p_bug_id, $p_message_id ) {
1123          $t_project_id = bug_get_field( $p_bug_id, 'project_id' );
1124          $t_user_access_level = user_get_access_level( $p_user_id, $t_project_id );
1125          $t_user_bugnote_order = user_pref_get_pref ( $p_user_id, 'bugnote_order' );
1126          $t_user_bugnote_limit = user_pref_get_pref ( $p_user_id, 'email_bugnote_limit' );
1127  
1128          $row = bug_get_extended_row( $p_bug_id );
1129          $t_bug_data = array();
1130  
1131          $t_bug_data['email_bug'] = $p_bug_id;
1132  
1133          if ( $p_message_id !== 'email_notification_title_for_action_bug_deleted' ) {
1134              $t_bug_data['email_bug_view_url'] = string_get_bug_view_url_with_fqdn( $p_bug_id );
1135          }
1136  
1137          if ( access_compare_level( $t_user_access_level, config_get( 'view_handler_threshold' ) ) ) {
1138              if ( 0 != $row['handler_id'] ) {
1139                  $t_bug_data['email_handler'] = user_get_name( $row['handler_id'] );
1140              } else {
1141                  $t_bug_data['email_handler'] = '';
1142              }
1143          }
1144  
1145          $t_bug_data['email_reporter'] = user_get_name( $row['reporter_id'] );
1146          $t_bug_data['email_project']  = project_get_field( $row['project_id'], 'name' );
1147  
1148          $t_bug_data['email_category'] = $row['category'];
1149  
1150          $t_bug_data['email_date_submitted'] = $row['date_submitted'];
1151          $t_bug_data['email_last_modified']   = $row['last_updated'];
1152  
1153          $t_bug_data['email_status'] = $row['status'];
1154          $t_bug_data['email_severity'] = $row['severity'];
1155          $t_bug_data['email_priority'] = $row['priority'];
1156          $t_bug_data['email_reproducibility'] = $row['reproducibility'];
1157  
1158          $t_bug_data['email_resolution'] = $row['resolution'];
1159          $t_bug_data['email_fixed_in_version'] = $row['fixed_in_version'];
1160  
1161          if ( !is_blank( $row['target_version'] ) && access_compare_level( $t_user_access_level, config_get( 'roadmap_view_threshold' ) ) ) {
1162              $t_bug_data['email_target_version'] = $row['target_version'];
1163          }
1164  
1165          if ( DUPLICATE == $row['resolution'] ) {
1166              $t_bug_data['email_duplicate'] = $row['duplicate_id'];
1167          }
1168  
1169          $t_bug_data['email_summary'] = $row['summary'];
1170          $t_bug_data['email_description'] = $row['description'];
1171  
1172          $t_bug_data['set_category'] = '[' . $t_bug_data['email_project'] . '] ' . $row['category'];
1173  
1174          $t_bug_data['custom_fields'] = custom_field_get_linked_fields( $p_bug_id, $t_user_access_level );
1175          $t_bug_data['bugnotes'] = bugnote_get_all_visible_bugnotes( $p_bug_id, $t_user_access_level, $t_user_bugnote_order, $t_user_bugnote_limit );
1176  
1177          # put history data
1178          if ( ( ON == config_get( 'history_default_visible' ) ) &&  access_compare_level( $t_user_access_level, config_get( 'view_history_threshold' ) ) ) {
1179              $t_bug_data['history']  = history_get_raw_events_array( $p_bug_id, $p_user_id );
1180          }
1181  
1182          # Sponsorship Information
1183          if ( ( config_get( 'enable_sponsorship' ) == ON ) && ( access_has_bug_level( config_get( 'view_sponsorship_total_threshold' ), $p_bug_id, $p_user_id ) ) ) {
1184              $t_sponsorship_ids = sponsorship_get_all_ids( $p_bug_id );
1185              $t_bug_data['sponsorship_total'] = sponsorship_get_amount( $t_sponsorship_ids );
1186  
1187              if ( access_has_bug_level( config_get( 'view_sponsorship_details_threshold' ), $p_bug_id, $p_user_id ) ) {
1188                  $t_bug_data['sponsorships'] = array();
1189                  foreach ( $t_sponsorship_ids as $id ) {
1190                      $t_bug_data['sponsorships'][] = sponsorship_get( $id );
1191                  }
1192              }
1193          }
1194  
1195          # MASC RELATIONSHIP
1196          if ( ON == config_get( 'enable_relationship' ) ) {
1197              $t_bug_data['relations'] = relationship_get_summary_text( $p_bug_id );
1198          }
1199  
1200          return $t_bug_data;
1201      }
1202  ?>


Généré le : Thu Nov 29 09:42:17 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics