Giter Club home page Giter Club logo

email's Introduction

Fuel Email Package.

A full fledged email class for Fuel. Send mails using php's mail function, sendmail or SMTP.

Summary

  • Send plain/text or html with (optional) alternative plain/text bodies using mail, sendmail or SMTP.
  • Add attachments, normal or inline and string or file.
  • Automatic inline file attachments for html bodies.
  • Configurable attachment paths.

Usage

$mail = Email::forge();
$mail->from('[email protected]', 'Your Name Here');

// Set to
$mail->to('[email protected]');

// Set with name
$mail->to('[email protected]', 'His/Her Name');

// Set as array
$mail->to(array(
	// Without name
	'[email protected]',
	
	// With name
	'[email protected]' => 'His/Her Name',
));

// Work the same for ->cc and ->bcc and ->reply_to


// Set a body message
$email->body('My email body');

// Set a html body message
$email->html_body(\View::forge('email/template', $email_data));

/**

	By default this will also generate an alt body from the html,
	and attach any inline files (not paths like http://...)

**/

// Set an alt body
$email->alt_body('This is my alt body, for non-html viewers.');

// Set a subject
$email->subject('This is the subject');

// Change the priority
$email->priority(\Email::P_HIGH);

// And send it
$result = $email->send();

Exceptions

+ \EmailValidationFailedException, thrown when one or more email addresses doesn't pass validation
+ \EmailSendingFailedException, thrown when the driver failed to send the exception

Example:

// Use the default config and change the driver
$email = \Email::forge('default', array('driver' => 'smtp'));
$email->subject('My Subject');
$email->html_body(\View::forge('email/template', $email_data));
$email->from('[email protected]', 'It's Me!');
$email->to('[email protected]', 'It's the Other!');

try
{
	$email->send();
}
catch(\EmailValidationFailedException $e)
{
	// The validation failed
}
catch(\EmailSendingFailedException $e)
{
	// The driver could not send the email
}

Priorities

These can me one of the following:

+ \Email::P_LOWEST - 1 (lowest)
+ \Email::P_LOW - 2 (low)
+ \Email::P_NORMAL - 3 (normal) - this is the default
+ \Email::P_HIGH - 4 (high)
+ \Email::P_HIGHEST - 5 (highest)

Attachments

There are multiple ways to add attachments:

$email = Email::forge();

// Add an attachment
$email->attach(DOCROOT.'dir/my_img.png');

// Add an inline attachment
// Add a cid here to point to the html
$email->attach(DOCROOT.'dir/my_img.png', true, 'cid:my_conten_id');

You can also add string attachments

$contents = file_get_contents($my_file);
$email->string_attach($contents, $filename);

By default html images are auto included, but it only includes local files. Look at the following html to see how it works.

// This is included
<img src="path/to/my/file.png" />

// This is not included
<img src="http://remote_host/file.jpeg" />

Drivers

The drivers allow the use of this library with mostly anything that can send mails.

Mailgun

Mailgun is an online service by Rackspace (http://www.mailgun.com/) that allows you to send emails by demand. You will need to install the mailgun library (https://github.com/mailgun/mailgun-php) with composer in your FuelPHP.

Once you have installed the package you will have to set up the config for your App:

<?php
return array(
	/**
	 * Override default Email.php settings
	 */
	'defaults' => array(
		'driver' => 'mailgun',
		'mailgun' => array(
			'key' => 'YOUR KEY',
			'domain' => 'YOUR DOMAIN',
			'endpoint' => null | 'OPTIONAL ALT. API ENDPOINT URL' // e.g. 'https://api.eu.mailgun.net/v3'
		),
	),
);

That's it. Questions?

email's People

Contributors

alrik11es avatar antitoxic avatar clouder avatar dhrrgn avatar digitales avatar ebvcrm avatar floorish avatar frankdejonge avatar it-can avatar jeteon avatar joaofoliveira avatar kenjis avatar khanashima avatar lexx27 avatar maca134 avatar mingfudesign avatar nickhagen avatar okhayat avatar pendexgabo avatar polmartinez avatar sagikazarmark avatar sahanh avatar scif avatar scootime avatar tomschlick avatar wanwizard avatar xploseof avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

email's Issues

Wordwarp exception

If in email config sets generate_alt to true and wordwrap to false(by default) on send email php throw exception in generate_alt().
Fix on line 1173 in email/driver.php:
return $wordwrap ? wordwrap($html, $wordwrap, $newline, true) : $html;

Problem with Email::header()

I think there is a bug with the array version of Email::header. The two-parameter version works fine, but the array version gets ignored.

Browsing the code, I suspect packages/email/classes/email/driver.php: in header(), the foreach uses $_header => $_value, but the following line uses $header / $value (line 455 in v1.5.3).

Chris

Headers are not MIME encoded

Hey,

in Germany we often send emails with german umlauts in the subject, some email clients can't handle german umlauts if they aren't mime encoded (email headers should only contain ASCII-chars).

My solution (it's not very clean):

class Email_Driver_Mail extends \Email_Driver
{
    /**
     * Send the email using php's mail function.
     *
     * @return  bool    success boolean.
     */
    protected function _send()
    {
        $message = $this->build_message();
        if ( ! @mail(static::format_addresses($this->to), mb_encode_mimeheader($this->subject, 'UTF-8', 'Q'), $message['body'], $message['header'], '-oi -f '.$this->config['from']['email']))
        {
            throw new \EmailSendingFailedException('Failed sending email');
        }
        return true;
    }

}

And in driver.php

protected function get_header($header = null, $formatted = true)
{
    if ($header === null)
    {
        return $this->headers;
    }

    if (array_key_exists($header, $this->headers))
    {
        $prefix = ($formatted) ? $header.': ' : '';
        $suffix = ($formatted) ? $this->config['newline'] : '';

        if($header == "Subject")
        {
            return $prefix.mb_encode_mimeheader($this->headers[$header], 'UTF-8', 'Q').$suffix;
        }

        return $prefix.$this->headers[$header].$suffix;
    }

    return '';
}

Names of email-adresses should be mime-encoded, too:
In driver.php I changed:

public function from($email, $name = false)
{
    $this->config['from']['email'] = (string) $email;
    $this->config['from']['name'] = (is_string($name)) ? mb_encode_mimeheader($name, 'UTF-8', 'Q') : false;

    return $this;
}

protected function add_to_list($list, $email, $name = false)
{
    if ( ! is_array($email))
    {
        $email = (is_string($name)) ? array($email => $name) : array($email);
    }

    foreach ($email as $_email => $name)
    {
        if (is_numeric($_email))
        {
            $_email = $name;
            $name = false;
        }

        if($name !== false)
        {
            $name = mb_encode_mimeheader($name, 'UTF-8', 'Q');
        }

        $this->{$list}[$_email] = array(
            'name' => $name,
            'email' => $_email,
        );
    }
}

But this is not the best solution, because if there are dots and other special chars in the email names the name should be quoted. And when they are quoted, extra quotes should be escaped.

This is the reason, why i present my solution as one solution but not as THE solutions. I'm sure, the maintainers will find a better and stable solution, which fits better in the coding style of fuelphp.

Thank you and best regards
Felix

Exception issues when host doesnt respond properly

So, I might just be too stupid to handle this properly, but if I am stupid enough other people will be too.

I've got a little script to send emails:

$mail=Email::forge();
        $mail->subject($title);
        $mail->html_body(\View::forge('email/newsletter'));
        foreach ($emails as $email){
            $mail->to($email);
            try
            {
                $mail->send();
                echo $email." OK\n";
            }
            catch(Exception $e)
            {
                // The driver could not send the email
                echo $email." ERROR\n";
            }
            $mail->clear_recipients();
        }

So, this works out alright, it's not perfect but does the job.
Now i ran into an issue
It keeps throwing exceptions when it recieves an invalid response

Uncaught exception Email\SmtpCommandFailureException: Got an unexpected response from host on command: [QUIT] expecting: 221 received:
Callstack:
#0 /www/cyperia/cyperia.org/lib/packages/email/classes/email/driver/smtp.php(160): Email\Email_Driver_Smtp->smtp_send('QUIT', 221)
#1 /www/cyperia/cyperia.org/lib/packages/email/classes/email/driver/smtp.php(37): Email\Email_Driver_Smtp->smtp_disconnect()
#2 /www/cyperia/cyperia.org/lib/core/base.php(428): Email\Email_Driver_Smtp->__destruct()
#3 /www/cyperia/cyperia.org/lib/core/base.php(428): Fuel\Tasks\Newsletter->run()
#4 /www/cyperia/cyperia.org/lib/packages/oil/classes/refine.php(106): call_fuel_func_array(Array, Array)
#5 [internal function]: Oil\Refine::run('newsletter', Array)
#6 /www/cyperia/cyperia.org/lib/packages/oil/classes/command.php(125): call_user_func('Oil\Refine::run', 'newsletter', Array)
#7 /www/cyperia/cyperia.org/oil(57): Oil\Command::init(Array)
#8 {main}

Previous exception:
Uncaught exception Email\SmtpCommandFailureException: Got an unexpected response from host on command: [RCPT TO:<[email protected]>] expecting: 250 or 251 received:
Callstack:
#0 /www/cyperia/cyperia.org/lib/packages/email/classes/email/driver/smtp.php(79): Email\Email_Driver_Smtp->smtp_send('RCPT TO:<balkow...', Array)
#1 /www/cyperia/cyperia.org/lib/packages/email/classes/email/driver.php(884): Email\Email_Driver_Smtp->_send()
#2 /www/cyperia/cyperia.org/app/tasks/newsletter.php(25): Email\Email_Driver->send()
#3 /www/cyperia/cyperia.org/lib/core/base.php(428): Fuel\Tasks\Newsletter->run()
#4 /www/cyperia/cyperia.org/lib/packages/oil/classes/refine.php(106): call_fuel_func_array(Array, Array)
#5 [internal function]: Oil\Refine::run('newsletter', Array)
#6 /www/cyperia/cyperia.org/lib/packages/oil/classes/command.php(125): call_user_func('Oil\Refine::run', 'newsletter', Array)
#7 /www/cyperia/cyperia.org/oil(57): Oil\Command::init(Array)
#8 {main}

And I cannot - for the life of me - seem to catch the second (top) exception which causes it to abort

Any ideas as to what to do?
This really seems like a bug.. or issue of some sort.
It should probably terminate the connection when it recieves an empty response, right?

Email::pipelining 503 Already authenticated

Using the Email::pipelining() function with SendGrid, Email_Driver_Smtp::smtp_authenticate() returns a 503 Already authenticated error status from SendGrid.

I managed to fix this by changing the 'use authentication' in Email_Driver_Smtp::__send() to

$authenticate = !empty($this->config['smtp']['username']) &&
                !empty($this->config['smtp']['password']) &&
                !($this->pipelining and !empty($this->smtp_connection));

Smtp: Sending HELP gets unexpected response

Hey,

this line: https://github.com/fuel/email/blob/1.1/develop/classes/email/driver/smtp.php#L118

<?php
$this->smtp_send('HELP', 214);

let throw a SmtpCommandFailureException in Email_Driver_Smtp::smtp_send(). It works great without it, but I actually don't know what sending help is for. I got the following message:

[HELP] expecting: 214
received: 502 5.5.2 Error: command not recognized

It seams that HELP is not supported by my mail server. Is it rellay important enough to stop sending the mail?

Don't attach https urls

In driver.php, Line 187:
if (($beginning = substr($image_url, 0, 7)) !== 'http://' and $beginning !== 'htts://' and substr($image_url, 0, 4) !== 'cid:')
Should be:
if (substr($image_url, 0, 7) !== 'http://' and substr($image_url, 0, 8) !== 'https://' and substr($image_url, 0, 4) !== 'cid:')

Comma in the name will send 2 emails instead of 1

Hello there,
We have a detected a problem while setting the send to name in the email class that when having a comma in the name it sends out 2 emails instead of 1.
Please fix it. For now we are using a work around for it.
Thanks,

namespace Fuel\Tasks;

class Testmail {

public function run(){

    $email = \Email\Email::forge();
    /* @var $email \Email\Email_Driver */

    $email->from('[email protected]');

            $email->to('[email protected]', 'firstname, lastname');   
            // this line will cause problems and send 2 emails

            $email->subject('testing comma name');
    $email->body('this is the body');
    $email->send();     
}

}

let the user decide to remove the html comments on html body emails

We use the email api as part of our CI suite and we mark the html body using comments to check if everything is correct.
We don't think that is up to the framework to decide if html comments should or not be stripped. That said, the framework should not alter the body other than the required manipulation to send the email.

I've added a new config parameter that let the use to decide if html comments should be removed

Email was not able to be transmitted.

I was not able to transmit email to the server to which the 'EHLO' command does not correspond.

in smtp.php

if($this->smtp_send('EHLO'.' '.\Input::server('SERVER_NAME', 'localhost.local'), 250, true) !== 250)
{
    // Didn't work? Try HELO
    $this->smtp_send('HELO'.' '.\Input::server('SERVER_NAME', 'localhost.local'), 250);
}

'smtp_send' is generating the exception, when an error code is acquired.
I think that it escapes from method, without transmitting the 'HELO' command.
The 'HELO' command is not actually transmitted.

Proposal : Email attach_paths default

I think it can be useful that "attach_paths" in email config file use :

// absolute path
'',

// fuelphp asset path
'__assets__',

// relative to docroot.
DOCROOT,

So a user can attach a file, without add the default asset path ...

$email->attach(\Asset::get_file('logo.gif', 'img'), true, 'cid:logo');

The config array key "assets" is only an example :)

Line Breaks w/ Double Quotes

I had major problems w/ the class trying to get emails to go out, until I changed the config to use double quotes instead of single quotes.

'newline' => '\r\n', needs to be 'newline' => "\r\n",

What is the correct name for a variable?

email/classes/email/driver.php
line:1025

case 'base64':
    return chunk_split(base64_encode($str), 76, $newline);

Variable names used in this method is $string?

Issue with mailgun driver and string_attach in version 1.8

attach works fine, but the way attach fills in the $attachments array seems to not be handled properly by the mailgun driver.

screen shot 2016-08-25 at 09 11 08

Here is the content of $this->attachments after the call to string_attach. So, indeed $file[0] is not defined.

(
    [inline] => Array
        (
        )

    [attachment] => Array
        (
            [cid:effc55b59e801141740f3d5c8f992ef6] => Array
                (
                    [file] => Array
                        (
                            [1] => Nicolas Lagier-1471824000.ics
                        )
                    [contents] => ...
                    [mime] => text/calendar
                    [disp] => attachment
                    [cid] => cid:effc55b59e801141740f3d5c8f992ef6
                )

        )

)

Email package: facilitate SMTP pipelining

Would it be possible to add a feature into the Email package to enable SMTP pipelining?

SendGrid allow up to 100 messages per SMTP connection, and it would be very useful to be able to take advantage of this facility, but I have no skills with SMTP to be able to implement such a feature myself.

Thanks, Chris

Tries to attach color code

Email\AttachmentNotFoundException [ Error ]:
Email attachment not found: #090D14

My HTML is:

[...]
        <table cellpadding="0" cellspacing="0" border="0" background="#090D14" align="center">
            <tr>
                <td>
[...]

(not sure if this is the right place to report bugs, looks like it though)

Email\Email_Driver wordwrap Bug

I found a bug.
Please check fix code.


[email.config]

wordwrap => 0

\Email\Email_Driver:attach()
-> chunk_split 0 size ERROR Bug?

old:
'contents' => chunk_split(base64_encode($contents), $this->config['wordwrap'], $this->config['newline']),

fix:
'contents' => chunk_split(base64_encode($contents), $this->config['wordwrap']? $this->config['wordwrap']: 76, $this->config['newline']),

BCC recipients not being stripped?

The BCC recipients appear to not being stripped from the headers, resulting in them being visible to everyone.

Tested this using Mail for Mac and Sparrow for Mac/iOS.

Mail on Google App

I have a gmail account and an account hosted on "gmail" but via Google Apps and aliased to my domain.

When sending mail (SMTP driver) to the gmail one: Everything is OK
Whend sending mail to the Google Aps one I have the following error :

Uncaught exception Email\SmtpCommandFailureException: Got an unexpected response from host on command: [RCPT TO:[email protected]] expecting: 250 or 251 received: 550 No Such User Here

While the address exists.

\EmailValidationFailedException shows an Array

\EmailValidationFailedException shows an array in the exception for failed email addresses instead of the email addresses, line 624 of driver.php

Debug of the $failed array:
Variable #1:
array
0 =>
array
'to' =>
array
'name' => string 'Trevor' (length=6)
'email' => string 'trovster' (length=8)

Exception message:
One or more email addresses did not pass validation: Array

Expected message(s):
One or more email addresses did not pass validation: trovster
One or more email addresses did not pass validation: trovster, [email protected], example

Multi sending

Example:

$mailer = Email::forge();
$body = View::forge('email/template', $data);
$mailer->html_body($body);
foreach ($mailing_list as $user) {
   $body->set('user', $user);
   $mailer->to($user['email'])->send();
}

Code like this throw error or work slow because multi sending not supported.
Rework:

  1. body/alt_body typed in Email_Driver::send(), not in setters
  2. Add method Email_Driver::before_send() called in Email_Driver::send() init properties only once
  3. Parse attachments from body is bad solution.
    Also:
    $cid = 'cid:'.md5(pathinfo($image_url, PATHINFO_BASENAME));

    'second/img.jpg' rewrite 'firtst/img.jpg'

Email\View_Body would solve it:

namespace Email;
use Fuel\Core\View;
class View_Body extends View
{
    protected $email;
    protected $attachments = [];
    
    public function __construct(Email_Driver $email, $file = null, $data = [], $filter = null)
    {
        $this->email = $email;
        $this->bind('email', $this->email);
        parent::__construct($file, $data, $filter);
    }
    
    public function set_filename($file, $reverse = false)
    {
        // TODO: add in config `'base_dir' => 'emails'` - directory with mail templates
        if ($dir = $this->email->get_config('email.defaults.base_dir'))
        {
            $file = $dir.DIRECTORY_SEPARATOR.$file;
        }
        
        return parent::set_filename($file, $reverse);
    }
    public function render($file = null)
    {
        // TODO: update method `clear_attachments` for optional clear
        $this->email->clear_attachments('inline');
        $this->attachments = [];
        
        return parent::render($file);
    }
    /**
     * Template helper.
     * @example `<img src="<?=$this->attach_inline($url)?>">`
     * @param string $path Path/URL to file
     * @return string CID
     */
    protected function attach_inline($path)
    {
        $id = 'cid:'.md5($path);
        if (!in_array($id, $this->attachments))
        {
            $this->email->attach($path, true, $id);
            $this->attachments[] = $id;
        }
        return $id;
    }
}

A timeout issue and an uncatchable Exception

Today I just found there was an error on my server (PHP 5.3.3).

I tried send an E-mail by smtp, but it simply timeout and throw an SmtpCommandFailureException (not SmtpTimeoutException). And if I tried to catch Exception by EmailSendingFailedException but it failed.

I've analyzed this issue and I found what happened exactly.

In /classes/email/driver/smtp.php, Line 289:

while($str = fgets($this->smtp_connection, 512))
{
    // If it counters a timeout, $str will simply get nothing and it won't run this code here.
    $info = stream_get_meta_data($this->smtp_connection);
    if($info['timed_out'])
    {
        throw new \SmtpTimeoutException('SMTP connection timed out.');
    }
...

As you can see, it never throw a SmtpTimeoutException correctly.

If I try to fix it by my own, I will encounter another SmtpCommandFailureException issue.

Although if it throws SmtpTimeoutException correctly, it will throw another SmtpCommandFailureException by "__destruct" function.

In /classes/email/driver/smtp.php, Line 30:

function __destruct()
{
    // If there is another Exception before this, it will be likely to throw SmtpCommandFailureException here.  When it happens, there no way I can catch this Exception by a "try" block except nested "try" blocks.
    if ( ! empty($this->smtp_connection))
    {
        $this->smtp_disconnect();
    }
}

So, I have to code like this to resolve the problem.

try
{
    $email->send();

    ...
}
catch(\EmailValidationFailedException $e)
{
    ...
}
catch(\EmailSendingFailedException $e)
{
    ...

    try
    {
        // I have to force it to tigger "__destruct" in order to prevent any unexpecting Exception.
        unset($email);
    }
    // catch EmailSendingFailedException **again**
    catch (\EmailSendingFailedException $e)
    {
        // Do nothing
    }

    ...
}

Email send with smtp problem.

Some email servers sends response with unwanted spaces in the begining of response.

On: APPPATH/packages/email/classes/email/driver/smtp.php
Line: 190

When retrieving the $number, $response must be trimmed. Otherwise it will throw Authenticate error.

$number = (int) substr(trim($response), 0, 3);

Sendmail - exception

Sending email with sendmail always throws an exception even if it was sent successfully:
Failed sending email through sendmail.

Auto generated Alt-Body has no line breaks

Hey,

I think there are two approches to get linebreaks from html.

  1. Put a line break for each p, br ...
  2. Use the line breaks in the html code.

For me the 2nd approch gives the better results. So I changed driver.php/generate_alt(), please see comments:

    protected static function generate_alt($html, $wordwrap, $newline)
{
    // $html = preg_replace('/\s{2,}/', ' ', $html); This line deletes all linebreaks, not good
    $html = trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/s', '', $html)));
    $lines = explode($newline, $html);
    $result = array();
    $first_newline = true;
    foreach ($lines as $line)
    {
        $line = trim($line);
        if ( ! empty($line))
        {
            $result[] = $line;
        }
    }

    $html = join($newline, $result);
            $html = html_entity_decode($html,  ENT_COMPAT, 'UTF-8'); // This isn't HTML anymore

    return wordwrap($html, $wordwrap, $newline, false); // False is more consistent with static::wrap_text() (URLs will not be cut)
}

And in driver.php/send() I had to change one more line, because it eats the new line breaks :

    // Don't wrap the text when using quoted-printable
    if ($wrapping and ! $qp_mode)
    {
        $this->body = static::wrap_text($this->body, $wrapping, $newline, $is_html);
        $this->alt_body = static::wrap_text($this->alt_body, $wrapping, $newline, false); // to false, alt-body  is definitely not HTML 
    }

Regards Felix

Dummy driver for unit testing

Use case:

I have a model to send email. And I want to test it. Now every time I run test, email is actually sent.

If there is a dummy driver which does nothing, I don't have to send email if I use it on test environment.
It is not needed sending email, because I do test of the model, not Email package.

Ref: http://fuelphp.com/forums/topics/view/9288

Add return type to docblock for \Email\Email::forge

Could you please add the return type to the docblock for the forge function so we can get type hinting on the returned object.

/*
 * ...
 * @return  Email_Driver
 */
public static function forge($setup = null, array $config = array())

You get a uninformative error if you try to auto-load your email config

I added email as an always load package, and I put a local copy of the email config in my app path.

I assumed you'd need to always-load the email config manually in my config file, as some packages need that.

You get an error about merging arrays, which I assume has something to do with the config not wanting to load twice?

Solution: Either
A. Just ignore an already loaded email config
B. Make a note in the docs about not auto-loading it

Whatever the case, having some standardization of when you do and do not need to load a package config would be great

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.