I would like to create in php file size validation for every single file. I used for loop to add attachments, and then created condition to check file, but it's not working. There's no error, but it send mail with oversized attachment, instead of stop. Without the size validation part, it sends mail without any problems.
For sending I used php mailer.
<?php
//Import PHPMailer classes into the global namespace
//These must be at the top of your script, not inside a function
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
//Load Composer's autoloader
require 'autoload.php';
//Create an instance; passing `true` enables exceptions
$mail = new PHPMailer(true);
$honeypot = $_POST['honey'];
$user_name = $_POST['name'];
$user_email = $_POST['email'];
$user_message = $_POST['message'];
$user_phone = $_POST['phone'];
$honeypot = trim($_POST["honey"]);
$max_size = 2 * 1024 * 1204; //2mb
$attachment = $_FILES['uploaded-file'];
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if(!empty($honeypot)) {
echo "NO SPAM!";
exit;
} else {
$mail = new PHPMailer; //From email address and name
$mail->isMail();
$mail->From = $user_email;
$mail->addAddress("jaroslaw.mor#gmail.com");
$mail->isHTML(true);
$mail->Subject = "Zapytanie ze strony www";
$mail->Body = "Telefon:$user_phone<br><br>Treść wiadomośći:<br>$user_message";
$mail->AltBody = "Telefon:$user_phone\n$content";
if(isset($attachment)) {
for ($i = 0; $i < count($_FILES['uploaded-file']['name']); $i++) {
if ($_FILES['uploaded-file']['error'] !== UPLOAD_ERR_OK) continue;
$file_TmpName = $_FILES['uploaded-file']["tmp_name"][$i];
$file_name = $_FILES['uploaded-file']["name"][$i];
if($_FILES['uploaded-file']["name"][$i]; > $max_size) {
echo "file is too big";
die();
}
else{
move_uploaded_file($fileTmpName, "uploads/" . $filename);
$mail-> AddAttachment("uploads/". $filename);
}
}//for
}//isset
if(!$mail->send()) {
echo "Mailer Error: " . $mail->ErrorInfo;
exit();
}
else {
header("Location: sent.html");
exit();
}//if send else
}//honey else end
}//post end
I have rebuilt my code a bit, and also complied with comments/clues.
But there's still the same problem.
This is a copy paste error
$_FILES['uploaded-file']["name"]['size'][$i]
According to the PHP documentation, size is under $_FILES['uploaded-file'] and not $_FILES['uploaded-file']['name']. See #yuxufabio's comment.
And the if (isset($attachments)) check is a bit weird. It'll always return an array (meaning true) even if it's empty. What you probably mean is if the form variable itself is set or not
if (isset($_FILES['uploaded-file'])) {
for ($i = 0; $i < count($_FILES['uploaded-file']['name']); $i++) {
Lastly, you should be checking if there's an error, as the upload is not garuanteed to work at the fault of the client, such as an empty file or a network error
if ($_FILES['uploaded-file']['error'][$i] !== UPLOAD_ERR_OK) continue;
...
if ($_FILES['uploaded-file']['size'][$i] > $maxsize) {
...
What I can see here is that you used the "move_upload_file" way earlier before you checked for the file size. And that means the file will be uploaded before checking to see if it's bigger or not. It should be something like this;
if( $_FILES['uploaded-file']["name"]['size'][$i] > $maxsize ) {
echo "file is too big";
die();
}else{
move_uploaded_file($fileTmpName, "uploads/" . $filename);
$mail-> AddAttachment("uploads/". $filename);
}
Related
Hi I have quite a large PhpMailer script that uploads 9 files and emails a HTML application form.
It gets sent via a pretty standard AJAX script. I have tested it on various devices and platforms and it all works fine. In fact I cant break it whatever I try to do however, my client's tenants seem to have found a way to break it.
They say they have used it and as far as they were concerned it sent successfully however there is no record of the email being sent or received or any of the files being uploaded to the server.
Here is the full script minus some form fields and also details of a connection to a database for spam checking.
if ( isset($_POST['email']) && isset($_POST['name']) && filter_var($_POST['email'], FILTER_VALIDATE_EMAIL) ) {
// detect & prevent header injections
$test = "/(content-type|bcc:|cc:|to:)/i";
foreach ( $_POST as $key => $val ) {
if ( preg_match( $test, $val ) ) {
exit;
}
}
$dateKey = date( 'd-m-Y--H-i-s' );
$my_email = "control#XXXXXXXXXXXX.com";
ob_start();
require("smtp/class.phpmailer.php");
$mail = new PHPMailer();
$mail->IsSMTP();
$mail->Host = "mail.XXXXXXXX.com";
$mail->SMTPAuth = true;
$mail->Username = $my_email;
$mail->Password = "XXXXXXXXXXX";
$mail->From = $mail->Username;
$mail->FromName = $_POST['name'];
$mail->Sender = $_POST['email'];
function clean($string) {
$string = str_replace(' ', '-', $string);
return preg_replace('/[^A-Za-z0-9\-]/', '', $string);
}
if(isset($_FILES)) {
$uploadOk = 1;
$fileString = '';
$fileMessage = 'FILEERROR(';
$files = $_FILES;
$target_dir = $_SERVER['DOCUMENT_ROOT'] . "/XXXXXXXXXX/uploads/";
foreach ( $_FILES as $key => $file ) {
$imageFileExt = strtolower( pathinfo( $file["name"], PATHINFO_EXTENSION ) );
$file['name'] = clean($_POST['name']). "_" . $key . "_" . $dateKey . "." . $imageFileExt;
$target_file = $target_dir . basename($file["name"]);
$imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
$check = getimagesize($file["tmp_name"]);
if($check === false) {
$fileMessage .= $key."=noimage,";
$uploadOk = 0;
}
// Allow certain file formats
else if($imageFileType !== "jpg" && $imageFileType !== "png" && $imageFileType !== "jpeg"
&& $imageFileType !== "gif" ) {
$fileMessage .= $key."=wrongfile,";
$uploadOk = 0;
}
// Check if file already exists
else if (file_exists($target_file)) {
$fileMessage .= $key."=fileexists,";
$uploadOk = 0;
}
// Check file size
else if ($file["size"] > 20000000) { //20mb
$fileMessage .= $key."=toobig,";
$uploadOk = 0;
}
$fileString .= strtoupper($key).": <a href='http://www.XXXXXXXXXXXX.com/XXXXXXXXX/uploads/".$file['name']."'>".$file['name']."</a><br>";
}
$fileMessage .= ')';
}
$mail->CharSet = 'utf-8';
$mail->Encoding = 'quoted-printable';
$bcc = "xxx#xxxxx.com";
$mail->AddBCC($bcc);
$mail->AddReplyTo($_POST['email']);
$mail->WordWrap = 50;
$mail->Body = "<p><strong>APPLICATION<br /></strong></p>
<p>Property ".$_POST['address']."<br />
<div style='background:#f1f1f1;padding:5px 15px; margin-bottom:20px;'><p><strong>APPLICANT DETAILS:<br /></strong></p><p>
Name: ".$_POST['name']."<br />
Email: ".$_POST['email']."<br />
Telephone: ".$_POST['tel']."<br />
Date of birth: ".$_POST['DOB']."<br />
National insurance number: ".$_POST['NI']."<br /></p></div>
<div style='background:#f1f1f1;padding:5px 15px; margin-bottom:20px;'><p><strong>ADDRESS<br /></strong></p><p>
Address: ".$_POST['address']."<br />
Time at address: ".$_POST['addLength']."<br />
Reason to move: ".$_POST['move']."<br />";
///more fields added to body here but not necessary to show
$mail->Body.="<div style='background:#f1f1f1;padding:5px 15px; margin-bottom:20px;'><p><strong>FILE ATTACHMENTS:<br /></strong></p><p>".$fileString."</p></div>";
$mail->IsHTML(true);
$mail->Subject = 'Application';
/* my own validation */
$formerrors = array();
$errorstring = "";
///connects to database here, details removed but checks against spam keywords and creates an array of $formerrors
$conn->close();
if (sizeof($formerrors) > 0){
$errorstring = "(" ;
foreach($formerrors as $key=>$value){
if($y < sizeof($formerrors) ){
$errorstring .= $value.",";
$y++;
} else{
$errorstring .= $value.")";
}
}
echo $errorstring;
#### file errors ####
} else if($uploadOk === 0){
echo $fileMessage;
}
else {
$mail->AddAddress("XXX#XXXXX.com", 'recipient');
///send here
if ($mail->Send() == true) {
if ($uploadOk === 1) {
if(isset($_FILES)) {
$uploadfiles = $_FILES;
// Compress image
function compressImage($source, $destination, $quality) {
$info = getimagesize($source);
if ($info['mime'] == 'image/jpeg') {
$image = imagecreatefromjpeg($source);
} elseif ($info['mime'] == 'image/gif') {
$image = imagecreatefromgif($source);
} elseif ($info['mime'] == 'image/png') {
$image = imagecreatefrompng($source);
}
imagejpeg($image, $destination, $quality);
}
foreach ( $uploadfiles as $key => $upfile ) {
$imageFileType = strtolower( pathinfo( $upfile['name'], PATHINFO_EXTENSION ) );
$fileName = clean($_POST['name']). "_" . $key . "_" . $dateKey . "." . $imageFileType;
$target_file = $target_dir . basename( $fileName );
$img_dir = "img/";
compressImage($upfile["tmp_name"], $target_dir . basename( $fileName ), 60);
}
}
}
echo 'Message sent successfully';
}
else {
echo "failed";
}
}
}
There are some classic mistakes in your code.
The issue is not PhpMailer.
Here is a summary of how to fix your most obvious problems:
Ensure you have the most up to date version of PhpMailer.
You don't seem to have any error detection on your Phpmailer... use PhpMailer Exceptions to find out if there's a sending issue within PhpMailer.
Use PhpMailer's extensive built in erorr logging with ->debugOutoput and ->SMTPDebug to detect emailer errors.
Turn on your PHP error logging to track errors, issues and notices and check your error logs regularly.
You Need to use PHP Error Logging! I copy and run your script and immediately come up with various notices and issues that you should have found right at the start.
If your host is not localhost you may need to check and confirm you are using the correct port, for example using $mail->Port = 587; instead of $mail->Port = 25 (default, I believe).
If your sending domain is another domain on the same server (as it looks like a mailing subdomain), then it's far easier simply to use "localhost" and avoid the whole authentication workload.
You seem to have misunderstood how PHP handled multiple file uploads , you seem to be expecting $_FILES[x]['name'] but what you're actually being given is $_FILES['name'][x]. You need to reorganise your $_FILES code to this end.
There is also a PHPMailer example for handling multiple uploads.
on your pathinfo call you should be testing the path to the tmp_name of the actual file and NOT the given original name. This is a serious security flaw.
It is advisable to clean $_POSTed data. Your $_POST['email'] at least should be run through FILTER_SANITIZE_EMAIL
Turn on PHP error logging
Do not trust your mechanism in compressImage to detect the correct image type. You should be using fileinfo on the source file rather than simply trusting the given type data from the $_FILES array which can be very easily manipulated by the unploadee.
If you complete all of the above and there is NOT a sending issue with PhpMailer, then use your server logs to check that the email sending program (sendmail or similar) actually received the sending request from PHP and what it did with it.
Your server logs will also outline sending issues from the server side (once PHP passes the data to your sending program).
You must remember that Sending is absolutely no guarentee of delivery, you should run 3rd party checks to ensure your server is correctly set up to send email, and includes basic spam tag avoidance techniques such as SPF, DKIM, DMARC, etc.
Check your PHP error logs
I am trying to limit the file size and type of attachments processed by phpmailer. The answer in this post does not solve the multiple attachments issue. The issue seems to be the form's input name with [] which converts form input to array. I am not able to write its correct syntax.
HTML is:
<input type="file" multiple="multiple" name="attach_file[]" />
PHP is:
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'src/Exception.php';
require 'src/PHPMailer.php';
$name = $_POST['name'];
$mail = new PHPMailer(true);
try {
$mail->setFrom('abc#abc.org', 'abc');
$mail->addAddress('xyz#xyz.com', 'xyz');
// Attachments
foreach(array_keys($_FILES['attach_file']['name']) as $key) {
$source = $_FILES['attach_file']['tmp_name'][$key];
$filename = $_FILES['attach_file']['name'][$key];
$mail->AddAttachment($source, $filename);
}
$mail->isHTML(true);
$mail->Subject = 'Case History';
$mail->Body = $name;
$mail->send();
echo 'Message has been sent';
}
catch (Exception $e) {
echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
}
If in foreach loop I use this:
$maxsize = 2 * 1024 * 1024; // 2 MB
$types = array('image/png', 'image/jpeg', 'image/gif'); // allowed mime-types
if(filesize($filename) < $maxsize && in_array(mime_content_type($filename),$types)){
$mail->AddAttachment($source, $filename);
}
I get these errors :
filesize(): stat failed
mime_content_type(): failed to open stream.
No such file or directory
What is the correct way of writing the IF condition when input name is for multiple attachments. Thanks.
You should note that $filename is just the original name of the file that has been uploaded (e.g. photo.jpg) - but the filesystem pathname of the uploaded file is actually $source (always some random filename, sitting in the OS temp folder).
I am building a website and have a form wherein the user can enter some fields, i.e. name, email, etc. but then also has the option to upload a file. I am using PHPMailer to construct an email that has the user's data as the email fields, and then sends it to me, so I can look at it. All works fine until the file upload. I am relatively new to PHP so it might be something little, but its driving me crazy. In the code below, I generate a new name for the uploaded file, and then append the file extension. Then I move it to a temp folder and try to attach it to the email via $mail->addAttachment. The email sends and everything, but the attached file has no extension--and when I manually download and add the appropriate extension, it works, but for some reason the file wont attach as the proper type.
// if one of the fields is set they all will be, i.e. the form has been submitted
if (isset($_POST['firstName']))
{
// array to hold possible runtime errors
$errors = array();
// if statement to see if user failed to enter one of the required fields
if (empty($_POST['firstName']) || empty($_POST['lastName']) || empty($_POST['email']) || empty($_POST['subject'])
|| empty($_POST['message']) || empty($_POST['phone']))
{
array_push($errors, 'Please enter all required fields');
}
// var to keep track of whether or not we have a file
$have_file = ($_FILES['inputFile']['error'] != UPLOAD_ERR_NO_FILE);
//checks for file upload as well
if ($have_file)
{
// here a file has been uploaded, so we make sure its an acceptable type
$ext_whitelist = array('dwg', 'asm', 'acp', '3dxml', 'cgr', 'dft', 'dxf', 'iam', 'idw', 'ipt', 'ipn', 'par', 'prt',
'skp', 'rvt', 'rfa',' sldasm', 'slddrw', 'sldprt', 'step', 'stl');
// var to store file array
$file = $_FILES['inputFile'];
// file properties stored for easier readability
$file_name = $file['name'];
$file_tmp = $file['tmp_name'];
$file_size = $file['size'];
$file_error = $file['error'];
// get file extension
$file_ext = explode('.', $file_name);
$file_ext = strtolower(end($file_ext));
if (!in_array($file_ext, $ext_whitelist))
{
if ($ext == 'php')
{
array_push($errors, 'Nice try');;
}
else
{
array_push($errors, 'Please enter a valid file type');
}
}
// checks file size
if ($file_size > 64000000)
{
array_push($errors, 'File too large, please call for further information');
}
}
// if we have an error, we just output that, or those, otherwise, we proceed
// with mailer
if (!empty($errors))
{
foreach ($errors as $err) { ?>
<p class="text-center" style="margin-top:20px;font-size:16px;">
<?php echo $err; ?>
</p>
<?php
}
}
// if here, there have been no errors
else
{
require 'PHPMailer/PHPMailerAutoload.php';
$mail = new PHPMailer;
//mail server setup
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = 'smtp.gmail.com'; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = ''; // SMTP username
$mail->Password = ''; // SMTP password
$mail->SMTPSecure = 'tls'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 587; // TCP port to connect to
//add To and From fields
$mail->From = '';
$mail->FromName = 'Mailer';
$mail->addAddress('');
$mail->isHTML(true); // Set email format to HTML
//add message contents
$mail->Subject = $_POST['subject'];
$mail->Body = $_POST['message'] . '<br><br>' . $_POST['firstName'] . ' ' . $_POST['lastName'] . '<br>' . $_POST['phone'];
// adds organization if its there
if (!empty($_POST['organization']))
{
$mail->Body .= '<br>' . $_POST['organization'];
}
// uploads/attaches file if there was one
if($have_file)
{
// give file unique name and set its destination as a temporary folder
$file_name_new = uniqid('', true) . '.' . $file_ext;
$file_destination = sys_get_temp_dir() . '\\' . $file_name_new;
if (move_uploaded_file($file_tmp, $file_destination))
{
echo $file_destination;
$mail->addAttachment($file_destination, 'Uploaded file');
}
else
{
?>
<p class="text-center" style="margin-top:20px;font-size:16px;">Error sending message, please call and let us know</p>
<?php
}
}
//send the message
if (!$mail->send())
{
?>
<p class="text-center" style="margin-top:20px;font-size:16px;">Error sending message, please call and let us know</p>
<?php
}
else
{
?>
<p class="text-center" style="margin-top:20px;font-size:16px;">Message sent! Thank you for visiting us today</p>
<?php
}
Any help would be greatly appreciated. I have left certain fields empty to prevent showing my info. i.e. $mail->From
#Hanoncs I managed to get it I think. The line:
$mail->addAttachment($file_destination, 'Uploaded file');
was renaming the file upon attachment to 'Uploaded file', literally. So, obviously, in the email there was no file extension on the file, because of the name. So all I had to do was change 'Uploaded file' to something with the extension, e.g. 'uploadedfile.ext' and it seemed to work. A silly, but enormously frustrating mistake, since all of the file upload handling seemed to work rather well. So the block now looks like this:
// uploads/attaches file if there was one
if($have_file)
{
// give file unique name and set its destination as a temporary folder
$file_name_new = uniqid('', true) . '.' . $file_ext;
$file_destination = sys_get_temp_dir() . '\\' . $file_name_new;
if (move_uploaded_file($file_tmp, $file_destination))
{
echo $file_destination;
$mail->addAttachment($file_destination, 'uploadedFile.dwg');
}
else
{
?>
<p class="text-center" style="margin-top:20px;font-size:16px;">Error sending message, please call and let us know</p>
<?php
}
}
Anyway, thanks for all your help, especially about the IDE, going to work on setting that up now.
First I would say you need to debug and check the file_ext at the time its appended and make sure its not empty.
To get the file extension use:
$file_ext = pathinfo($file_name, PATHINFO_EXTENSION);
Let me know your result and I can assist further.
I am trying to allow users to upload outlook email messages saved as .msg files but my error system says the messages are not part of my allowed bunch. I have tried 3 different outlook types but to no avail. What is the correct mime type?
Here is my shortened code.
$whitelist = array('application/outlook','application/msoutlook','application/vnd.ms-outlook');
$errors = false;
if (isset($_POST['submit'])) {
$uniqueid = time().$_SESSION['webuserid'];
$description = htmlspecialchars($_POST['description']);
if (empty($_FILES['file']['name'])) {
$message = "<b> * No File Selected</b>"; $errors = true; }
if ($_FILES['file']['size'] > 5000000 && !empty($_FILES['file']['name'])) {
$message = "<b> * 5MB Max Upload</b>"; $errors = true; }
if (!in_array($_FILES['file']['type'], $whitelist) && !empty($_FILES['file']['name'])) {
$message = "<b> * PDF, Excel, Outlook Message, Word Format Only</b>"; $errors = true; }
Thanks
So why don't you var_dump($_FILES['file']['type']); for a .msg file and see what it says? Then add that to your $whitelist.
You'll probably find the mimetype is application/vnd.msoutlook
Ive been working on create a file upload form using PHPmailer to send as attachments.
Ive finally got it to send the email, but its not sending the attachment. Here's my HTML form:
<input type="file" class="fileupload" name="images[]" size="80" />
And here's my php processor code:
<?php
require("css/class.phpmailer.php");
//Variables Declaration
$name = "the Submitter";
$email_subject = "Images Attachment";
$Email_msg ="A visitor submitted the following :\n";
$Email_to = "jonahkatz#yahoo.com"; // the one that recieves the email
$email_from = "someone#someone.net";
$attachments = array();
//
//
//------Check TYPE------\\
uploadFile();
//
//==============upload File Function============\\
//
function uploadFile() {
global $attachments;
foreach($_FILES['images']['name'] as $key => $value)
{
//
if(!empty($value))
{
$filename = $value;
//the Array will be used later to attach the files and then remove them from ser
ver ! array_push($attachments, $filename);
$dir = "uploads/$filename";
$success = copy($_FILES['images']['tmp_name'][$key], $dir);
}
//
}
$dir ="uploads/$filename";
if ($success) {
echo " Files Uploaded Successfully<BR>";
SendIt();
//
}else {
exit("Sorry the server was unable to upload the files...");
}
//
}
//
//==== PHP Mailer With Attachment Func ====\\
//
function SendIt() {
//
global $attachments,$name,$Email_to,$Email_msg,$email_subject,$email_from;
//
$mail = new PHPMailer();
$mail->IsQmail();// send via SMTP
$mail->From = $email_from;
$mail->FromName = $name;
$mail->AddAddress($Email_to);
$mail->AddReplyTo($email_from);
$mail->WordWrap = 50;// set word wrap
//now Attach all files submitted
foreach($attachments as $key => $value) { //loop the Attachments to be added ...
$mail->AddAttachment("uploads"."/".$value);
}
$mail->Body = $Email_msg."Name : ".$name"\n";
//
$mail->IsHTML(false);// send as HTML
$mail->Subject = $email_subject;
if(!$mail->Send())
{
echo "Message was not sent <p>";
echo "Mailer Error: " . $mail->ErrorInfo;
exit;
}
//
echo "Message has been sent";
// after mail is sent with attachments , delete the images on server ...
foreach($attachments as $key => $value) {//remove the uploaded files ..
unlink("uploads"."/".$value);
}
//
}
//
?>
Ive checked, and the file IS being saved in the directory "uploads". Here are the errors im receiving:
Files Uploaded Successfully
Message was not sent
Notice: Undefined property: phpmailer::$ErrorInfo in /usr/home/jak2234/public_html/new_form/phpmailerprocess.php on line 69
Mailer Error:
If anyone can spot the errors or provide some input how to this that would be so helpful! Thanks in advanced!
Jonah
Ive replaced
foreach($attachments as $key => $value) { //loop the Attachments to be added ...
$mail->AddAttachment("uploads"."/".$value);
With
foreach(array_keys($_FILES['files']['name']) as $key) {
$source = $_FILES['files']['tmp_name'][$key]; // location of PHP's temporary file for this.
$filename = $_FILES['files']['name'][$key]; // original filename from the client
$mail->AddAttachment($source, $filename);
}
And now here are my new errors:
Notice: Undefined index: files in /usr/home/jak2234/public_html/new_form/phpmailerprocess.php on line 58
Warning: array_keys() expects parameter 1 to be array, null given in /usr/home/jak2234/public_html/new_form/phpmailerprocess.php on line 58
Warning: Invalid argument supplied for foreach() in /usr/home/jak2234/public_html/new_form/phpmailerprocess.php on line 58
Strict Standards: Creating default object from empty value in /usr/home/jak2234/public_html/new_form/phpmailerprocess.php on line 68
Fatal error: Call to undefined method stdClass::IsHTML() in /usr/home/jak2234/public_html/new_form/phpmailerprocess.php on line 70
As I said in your other question, the first warning is due to you using $filename in line 10 of your script, without having assigned a value to it first:
$dir ="uploads/$filename"; // $filename has NOT been defined at this point.
As well, for your attachments, why not simply do:
foreach(array_keys($_FILES['files']['name']) as $key) {
$source = $_FILES['files']['tmp_name'][$key]; // location of PHP's temporary file for this.
$filename = $_FILES['files']['name'][$key]; // original filename from the client
$mail->AddAttachment($source, $filename);
}
There's no need to do all the file copying, building your own paths, etc... Just directly attach the temporary file PHP creates for you, and name it with whatever the original filename was.
Your script is far more complicated than it needs to be.