PHP电子邮件 - 纯文本格式的间距

I'm want to send php mail in plain text and i am NOT allowed to use html but I'm having issues with spacing. The output should look like this:

Item         Qty        Price
Whatever      1          5000USD
Whatever2     2            50USD

 Subtotal                5050USD
 Tax                       50USD

 TOTAL                   5100USD

Which is pretty difficult considering amounts and product names always vary so it ends up looking very messy. Since columns widths are always going to be different i would like to right-align the last column so everything looks aligned and clean. Is there any practical method to do this?

Thank you.

EDIT:

This is my current code:

function render($indent = "", InvoicePayment $payment = null)
{
    $prefix = (!is_null($payment) && !$payment->isFirst()) ? 'second' : 'first';
    $tm_added = is_null($payment) ? $this->tm_added : $payment->dattm;

    $newline = "
";

    $price_width = max(mb_strlen(Am_Currency::render($this->{$prefix . '_total'}, $this->currency)), 8);

    $column_padding = 3;
    $column_title_max = 60;
    $column_title_min = 20;
    $column_qty = 15;
    $column_num = 3;
    $column_amount = $price_width;
    $space = str_repeat(' ', $column_padding);

    $max_length = 0;
    foreach ($this->getItems() as $item) {
        $max_length = max(mb_strlen(___($item->item_title)), $max_length);
    }

    $column_title = max(min($max_length, $column_title_max), $column_title_min);
    $row_width = $column_num + $column_padding +
                 $column_title + $column_padding +
                 $column_qty + $column_padding +
                 $column_amount + $column_padding;

    $column_total = $column_title +
                    $column_qty + $column_padding;
    $total_space = str_repeat(' ', $column_padding + $column_num + $column_padding);

    $border = $indent . str_repeat('-', $row_width) . "$newline";

    $out = $indent . ___("Invoice") . ' #' . $this->public_id . " / " . amDate($tm_added) . "$newline";
    $out .= $border;
    $out .= $indent . sprintf("{$space}%{$column_num}s{$space}%-{$column_title}s{$space}%{$column_qty}s{$space}%{$price_width}s$newline",
            " ", ___('Subscription/Product Title'), ___('Quantity'), ___('Unit Price'));
    $out .= $border;
    $num = 1;
    foreach ($this->getItems() as $item) {
        $title = explode("
", $this->wordWrap(___($item->item_title), $column_title, "
", true));
        $out .= $indent . sprintf("{$space}%{$column_num}s{$space}%-{$column_title}s{$space}%{$column_qty}s{$space}%{$price_width}s$newline",
            $num . '.', $title[0], $item->qty, Am_Currency::render($item->{$prefix . '_price'}, $this->currency));
        for ($i=1; $i<count($title); $i++)
            $out .= $indent . sprintf("{$space}%{$column_num}s{$space}%-{$column_title}s$newline", ' ', $title[$i]);
        $num++;
    }
    $out .= $border;
    if ($this->{$prefix . '_subtotal'} != $this->{$prefix . '_total'})
        $out .= $indent . sprintf("{$total_space}%-{$column_total}s{$space}%{$price_width}s$newline", ___('Subtotal'), Am_Currency::render($this->{$prefix . '_subtotal'}, $this->currency));
    if ($this->{$prefix . '_discount'} > 0)
        $out .= $indent . sprintf("{$total_space}%-{$column_total}s{$space}%{$price_width}s$newline", ___('Discount'), Am_Currency::render($this->{$prefix . '_discount'}, $this->currency));
    if ($this->{$prefix . '_shipping'} > 0)
        $out .= $indent . sprintf("{$total_space}%-{$column_total}s{$space}%{$price_width}s$newline", ___('Shipping'), Am_Currency::render($this->{$prefix . '_shipping'}, $this->currency));
    if ($this->{$prefix . '_tax'} > 0)
        $out .= $indent . sprintf("{$total_space}%-{$column_total}s{$space}%{$price_width}s$newline", ___('Tax'), Am_Currency::render($this->{$prefix . '_tax'}, $this->currency));
    $out .= $border;
    $out .= $newline;
    $out .= $indent . sprintf("{$total_space}%-{$column_total}s{$space}%{$price_width}s$newline", ___('Total'), Am_Currency::render($this->{$prefix . '_total'}, $this->currency));
    if ($this->rebill_times) {
        $terms = explode("
", $this->wordWrap(___($this->getTerms()), $row_width, "
", true));
        foreach ($terms as $term_part)
            $out .= $indent . $term_part . $newline;
        $out .= $border;
    }
    return $out;
}

Spacing will never work as it will be very diffcult to manage your code.

Instead map those fields/values in a HTML table and set the border to 0 , also you should render your mail as HTML for the above things to work.

To do this.. go to http://www.tablesgenerator.com/html_tables and generate the table as per you want , Click generate and you will get the HTML source code for it..

enter image description here

After that, you can paste those source on your email message , Don't forget to set the border to 0. Render your mail headers to HTML , to send this as an HTML mail.

// To send HTML mail, the Content-type header must be set
$headers  = 'MIME-Version: 1.0' . "
";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "
";

Mail code grabbed from PHP Manual.

If you give multiple spaces between two elements then HTML will only consider single space. You can use &nbsp for spacing. Another best way to do this is to write an HTML table for that.

you can use a table for this

<table width="600" cellpadding="0" cellspacing="0" border="0" align="center">
  <tr>
     <td>Item</td>  <td>Qty</td>  <td>Price</td>
  </tr>

  <tr>
     <td>Whatever1</td>  <td>1</td>  <td>5000USD</td>
  </tr>

   <tr>
     <td>Whatever2</td>  <td>2</td>  <td>50USD</td>
  </tr>

  <tr><td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td></tr>

   <tr>
     <td>Subtotal</td>  <td>&nbsp;</td>  <td>5050USD</td>
  </tr>

   <tr>
     <td>Tax</td>  <td>&nbsp;</td>  <td>50USD</td>
  </tr>

   <tr><td>&nbsp;</td> <td>&nbsp;</td> <td>&nbsp;</td></tr>

   <tr>
     <td>Total</td>  <td>&nbsp;</td>  <td>5100USD</td>
  </tr>



</table>